欧几里得

【Exgcd】扩展欧几里得算法

柔情痞子 提交于 2020-01-18 18:20:22
Description    欧几里德算法 又称辗转相除法,是指用于计算两个正整数a,b的最大公约数。应用领域有数学和计算机两个方面。计算公式 。    扩展欧几里德算法 是用来在已知a, b,求解一组 x,y 使得:ax + by = gcd(p,q) (解一定存在,根据数论中的相关定理)。    本题任务 :给定任意整数a,b,c,求方程 ax + by = c 的整数解,输出其中x是最小的正整数的一组。 Input   若干行,每行一组数据:a,b,c。他们都是int范围内的整数。 Output   每组数据输出一行,若给定方程没有整数解,输出"No solution",否则输出x是最小的正整数的一组。 Sample Input 1 1 1 1 1 2 1000 12 20 7 27 -45 18 6 15 9 Sample Output 1 1 0 2 499 No solution 4 2 4 -1 Hint a,b,c在int范围内,且都不为0。 1.理论部分 欧几里得算法 求最大公因数: int gcd(int a, int b) { if(b == 0) return a; else return gcd(b, a%b); } 其中模运算可定义为:(以下除法都是指下取整除法) a%b = a-a/b*b 扩展欧几里得算法: 已知整数a、b

【知识总结】数论全家桶

人盡茶涼 提交于 2020-01-18 05:25:05
NOI2019 不到一周了,开始总复习 颓废 咯 ~ 一些数论算法以前已经写过了,本文主要用于总结一些杂七杂八的小算法,查缺补漏。 传送门 (说到传送门,Steam 夏日大促 Portal 2 只要 3 CNY 就是一玩起来就 3D 眩晕没法学习) : 【知识总结】线性筛_杜教筛_Min25筛 【知识总结】扩展卢卡斯定理(exLucas) 【知识总结】Miller-Robin和Pollard-Rho(咕 ~ ) 本文将涉及以下内容: 更相减损术、欧几里得算法及扩展欧几里得算法 逆元 中国剩余定理及扩展中国剩余定理 Lucas 定理 本文中所有字母如无特殊说明均默认为正整数。 更相减损术、欧几里得算法及扩展欧几里得算法 更相减损术 首先一个很显然的结论: \[ \gcd(a,b)=\gcd(a,a-b)(a\geq b) \] (证明略,反正看起来很显然就对了 —— 虽然这个显然的结论经常想不到 QAQ ) 于是可以就照着这个一直递归(或者迭代)下去,边界是 \(\gcd(a,0)=a\) 。 欧几里得算法 这就是大家熟悉的 \(\gcd(a,b)=\gcd(a \bmod b, b)\) ,可以从上面那个结论推过来。同样可以通过递归的方式计算: int gcd(const int a, const int b) { return b ? gcd(b, a % b) : a; }

欧几里得算法

十年热恋 提交于 2020-01-10 08:04:44
一 代码 package Euclid; /** * Copyright (C), 2020-2020, XXX有限公司 * FileName: Euclid * Author: cakin * Date: 2020/1/6 * Description: 计算两个非负数p和q的最大公约数:若q=0,则最大公约数为p。否则,将p除以q得到余数r,p和q的最大公约数即为q和r的最大公约数 * 18和8的最大公约数: * 第一次递归:p=18,q=8:r=18%8=2,所以18和8的最大公约数为8和2的最大公约数 * 第二次递归:p=8,q=2:r=8%2=0,最大公约数为2和0的最大公约数 * 第三次递归:p=2,q=0,得到最大公约数为2 */ public class Euclid { public static void main( String[] args ) { System.out.println(gcd(8,18)); } public static int gcd(int p,int q){ if(q==0){ return p; } int r = p %q; return gcd(q,r); } } 二 测试结果 2 三 说明 用于求最大公约数。 四 参考代码 https://gitee.com/cakin24/Algorithm/tree/master/src

网络安全RSA加密

折月煮酒 提交于 2020-01-08 01:44:54
网络安全课相关知识: RSA 预备知识 1.1 快速幂算法 顾名思义,快速幂就是快速算底数的$n$次幂。其时间复杂度为${\rm{O(log n)}}$,与朴素的$O\left( n \right)$相比,效率有了极大的提高。具体可以参考百度百科:快速幂。 1.2 扩展欧几里得算法 扩展欧几里得算法(英语:Extended Euclidean algorithm)是欧几里得算法(又叫辗转相除法)的扩展。已知整数a、b,扩展欧几里得算法可以在求得a、b的最大公约数的同时,能找到整数x、y(其中一个很可能是负数),使它们满足贝祖等式 ax+by=gcd(a,b). ax+by=gcd(a,b). 如果$a$是负数,可以把问题转化成 $\left| a \right|\left( { - x} \right){\rm{ }} + {\rm{ }}by{\rm{ }} = {\rm{ }}gcd\left( {\left| a \right|,b} \right)$($\left| a \right|$为a的绝对值),然后令$x\prime {\rm{ }} = {\rm{ }}\left( { - x} \right)$。具体可以参考维基百科:扩展欧几里得。 1.3 米勒-拉宾素性检验算法 要测试${\rm{N}}$是否为素数,首先将${\rm{N - 1}}$分解为${2^s}d$

网络安全RSA加密

心不动则不痛 提交于 2020-01-04 03:26:07
网络安全课相关知识: RSA 预备知识 1.1 快速幂算法 顾名思义,快速幂就是快速算底数的$n$次幂。其时间复杂度为${\rm{O(log n)}}$,与朴素的$O\left( n \right)$相比,效率有了极大的提高。具体可以参考百度百科:快速幂。 1.2 扩展欧几里得算法 扩展欧几里得算法(英语:Extended Euclidean algorithm)是欧几里得算法(又叫辗转相除法)的扩展。已知整数a、b,扩展欧几里得算法可以在求得a、b的最大公约数的同时,能找到整数x、y(其中一个很可能是负数),使它们满足贝祖等式 ax+by=gcd(a,b). ax+by=gcd(a,b). 如果$a$是负数,可以把问题转化成 $\left| a \right|\left( { - x} \right){\rm{ }} + {\rm{ }}by{\rm{ }} = {\rm{ }}gcd\left( {\left| a \right|,b} \right)$($\left| a \right|$为a的绝对值),然后令$x\prime {\rm{ }} = {\rm{ }}\left( { - x} \right)$。具体可以参考维基百科:扩展欧几里得。 1.3 米勒-拉宾素性检验算法 要测试${\rm{N}}$是否为素数,首先将${\rm{N - 1}}$分解为${2^s}d$

欧几里得

故事扮演 提交于 2019-12-06 15:27:15
欧几里得 关于欧几里得定理这个东西,我在全网上也没有找到什么好的讲解。所以决定自己来写一写 自己都证了好久 欧几里得的应用一般是用在求 \(gcd\) 的时候用的,用辗转相除发递归求 \(gcd\) 。 相信大家一般都是直接用的,没有想过去证明它, 认为他很显然 是吧。 我最开始也是这样以为的,但是却发现自己证了好久。 肯定是我太菜了 不多废话。。。 我就只讲一下欧几里得求 \(gcd\) 的证明。 好像欧几里得就这个作用 先写出众所周知的公式: \(gcd(a,b) = gcd(b, a % b)\) 然后不断递归就行了。 现在来证明如上等式: 令 \(gcd(a, b) = c\) , 那么, \(a = c * k1\) , \(b = c * k2\) ( \(k1\) 和 \(k2\) 互质) 那么, \(gcd(a, b) = gcd(c * k1, c * k2)\) \(a % b = c * k1 % c * k2 = (k1 % k2) * c\) 上面这一步需要好好理解一下,如果 \(k1\) 和 \(k2\) 不互质的话就没有这个结论 证明如下: 原式可以展开如下 : \(c * k1 = c * k2 * t + e\) 这个 \(t\) 可以为 \(0\) ,而这个 \(e\) 就是 \(a % b\) 了 \(a % b = c * k1 - c *

扩展欧几里得

北战南征 提交于 2019-12-06 13:53:59
\(ax_1+by_1=gcd(a,b)\) \(bx_2+(a \mod b)y_2=gcd(b,a \mod b)\) \(\because gcd(a,b)=gcd(b,a\mod b)\) \(\therefore ax_1+by_1=bx_2+(a\mod b)y_2\) \(\because a\mod b=a-\lfloor \frac{a}{b}\rfloor b\) \(\therefore ax_1+by_1=bx_2+ay_2-\lfloor \frac{a}{b}\rfloor by_2=ay_2+b(x_2-\lfloor\frac{a}{b}\rfloor y_2)\) \(\therefore x_1=y_2,y_1=x_2-\lfloor\frac{a}{b}\rfloor y_2,x1,y1为当前层,x2,y2为递归的下一层的值\) \(\because 最后一层,a=g,b=0,ax+by=g\) \(\therefore 设x=1,y=0\) int exgcd(int a, int b, int &x, int &y) { if (!b) { x = 1; y = 0; return a; } int d = Exgcd(b, a % b, x, y); int t = x; x = y; y = t - (a / b) * y;

类欧几里得算法学习笔记

荒凉一梦 提交于 2019-12-06 12:49:13
如何求 \(\sum_{i=0}^ni^{k1}\lfloor\frac{ai+b}{c}\rfloor^{k2}\) ? \((1\leqslant n,a,b,c\leqslant10^9,k1+k2\leqslant 10)\) 设 \(f(n,a,b,c)[k1][k2]\) 表示原式的值,则: 若 \(a\geqslant c\) ,设 \(a=pc+q(0\leqslant q<c)\) ,则 \[\begin{align} &\;\;\;\;\;f(n,a,b,c)[k1][k2]\\ &=\sum_{i=0}^ni^{k1}\lfloor\frac{ai+b}{c}\rfloor^{k2}\\ &=\sum_{i=0}^ni^{k1}(pi+\lfloor\frac{qi+b}{c}\rfloor)^{k2}\\ &=\sum_{i=0}^ni^{k1}\sum_{j=0}^{k2}\text{C}_{k2}^jp^ji^j\lfloor\frac{qi+b}{c}\rfloor^{k2-j}\\ &=\sum_{j=0}^{k2}\text{C}_{k2}^jp^j\sum_{i=0}^ni^{k1+j}\lfloor\frac{qi+b}{c}\rfloor^{k2-j}\\ &=\sum_{j=0}^{k2}\text{C}_{k2}^jp^jf(n,q,b

欧几里得算法

不羁岁月 提交于 2019-12-05 05:29:33
一、背景及介绍   在数学中, 辗转相除法 ,又称 欧几里得算法 (英语: Euclidean algorithm),是求 最大公约数 的算法。两个 整数 的 最大公约数 是能够 同时整除 它们的 最大的正整数 。辗转相除法基于如下原理:两个 整数 的 最大公约数 等于 其中较小的数 和 两数相除余数 的最大公约数。例如,252和105的最大公约数是21(252 = 21 × 12;105 = 21 × 5 );因为 252 − 105 = 21 × (12 − 5) = 147 ,所以147和105的最大公约数也是21。 二、递归与非递归实现 1 /** 2 * 递归实现 3 * @param m 4 * @param n 5 * @return 6 */ 7 public static int gcdRecu(int m, int n) { 8 if (n == 0) { 9 return m; 10 } else { 11 return gcdRecu(n, m%n); 12 } 13 } 14 15 /** 16 * 迭代法 17 * @param m 18 * @param n 19 * @return 20 */ 21 public static int gcdIter(int m, int n) { 22 int t = 1; 23 while (t != 0) {

拓展欧几里得算法(数论)

家住魔仙堡 提交于 2019-12-04 20:44:51
拓展欧几里得 是用来计算已经知道 a 和 b 的时候,让你去求 a*x+b*y=GCD(a,b) 的一组解 (x,y) 。(首先根据一些相关数论证明,这个解是一定存在的) GCD(a,b) 应该都知道吧,求a和b的最小公约数。 因为GCD(a,b)=GCD(b,a%b),所以a*x+b*y=GCD(b,a%b),也就意味着a*x+b*y=b*x-(a%b)*y,进而可以得出x*a+y*b=y*a+(x-y*a/b)*b; 最后推到最后是当b为0的时候,a为最小公约数,根据第一个式子,a*x+b*y=a; (但是此时的x和y是进过多次替换过的,并不是最开始的那个x,y了) 但是我们可以递归回我们需要的那个最开始的x,y。 这就是拓展欧几里得。 代码实现: #include<stdio.h> #include<string.h> #include<stdlib.h> #include<algorithm> using namespace std; int x,y; int ex_gcd(int a,int b) { int ret,tem; if(!b) { x=1;y=0; return a; } ret=ex_gcd(b,a%b); tem=x; x=y; y=tem-a/b*y; return ret; } int main() { int a,b,z; scanf("%d%d"