欧几里得与扩展

欧几里得:

gcd递归定义:对于任意正整数b,gcd(a,b)= gcd(b,a mod b)。

证明:

  

  只需要证明上面两者能相互整除。

  设gcd(a,b)= d,所以d | a 且 d | b。由带余除法可以得出:

  a mod b = a - qb。其中 q = └a / b┘.所以 a mod b 是a 和 b的一个线性方程组合,
  
  所以d |a mod b。又因为 d | b,所以 d | gcd(b,a mod b),即gcd(a,b)|gcd(b,a mod b)。
  
  证明gcd(b,a mod b)|gcd(a,b)和上述过程几乎一样。

  

代码实现:

  

 1 #include <iostream>
 2 #include <cstdio>
 3 using namespace std;
 4 int a,b;
 5 int gcd(int a,int b)
 6 {
 7     if(a<b)swap(a,b);        //此处注意,why?仔细想想。
 8     return a%b==0?b:gcd(b,a%b);
 9 }
10 int main()
11 {
12     scanf("%d%d",&a,&b);
13     printf("%d",gcd(a,b));
14 }

gcd 比较简单,接下来才是重头戏 --- 扩展。

扩展欧几里得:

  这东西看似没啥用,实际其应用范围很广(逆元,不定方程...)。

  现在我们有这样一个问题:

    求解不定方程 ax + by = gcd(a,b).(假设 a >= b ).

 

当 b=0 时有 gcd(a,b)=a,此时 x=1,y=0
当 b 不为 0 时,根据 GCD 递归定理 gcd(a,b)=gcd(b, a mod b)
可得 ax+ by=gcd(a, b)=gcd(b, a mod b)=bx′ +(a mod b)y′
即 ax+by=bx′+(a mod b)y′ = bx′+(a−b)×⌊a/b⌋y′
移项得 ax+by=bx′+(a mod b)y=ay‘+b(x-⌊a/b⌋y)

所以x=y‘,y=x‘-⌊ a/b ⌋y‘.

  设(xo,yo)是不定方程 ax+by=m 的一组解,(a,b)=g,那么全部解为

    (xo+(b/g)t , yo - (a/g)t),其中 t 为所有整数.

  

模板代码:

 1 #include <cstdio>
 2 int exgcd(int a, int b, int &x, int &y)        //非递归版
 3 {
 4     int d;
 5     if (!b) x = 1, y = 0, d = a;
 6     else
 7     {
 8         d = exgcd(b, a % b, y, x);
 9         y -= (a / b) * x;
10     }
11     return d;
12 }
13 int exgcd(int a, int b, int &x, int &y)        //递归版
14 {
15     int d;
16     return !b ? (x = 1, y = 0, a) : (d = exgcd(b, a % b, y, x), y -= (a / b) * x, d);
17 }
18 int main()
19 {
20     int a, b, x, y;
21     scanf ("%d%d", &a, &b);
22     printf("%d\n", exgcd(a, b, x, y));
23     printf("%d %d\n", x, y);
24 }

习题练习:

  NOIP 2012 同余方程

  求关于 x 的同余方程ax ≡ 1(mod b) 即求解 ax + by = 1  中的 x 值,注意题目要求 正整数。

  不是模板,胜似模板。

  代码:

 1 #include <cstdio>
 2 int exgcd(int a, int b, int &x, int &y) {
 3     int d;
 4     return !b ? (x = 1, y = 0, a) : (d = exgcd(b, a % b, y, x), y -= (a / b) * x, d);
 5 }
 6 int main()
 7 {
 8     int a, b, x, y;
 9     scanf ("%d%d", &a, &b);
10     exgcd(a, b, x, y);
11     int k=(0-x) /b;
12     x=x+k*b;
13     while(x<0){ x+=b; }     //处理负数
14     printf("%d", x);
15 }

作者:RMY

出处:https://www.cnblogs.com/rmy020718/p/9192002.html

原文地址:https://www.cnblogs.com/rmy020718/p/9192002.html

时间: 2024-10-17 02:59:14

欧几里得与扩展的相关文章

数论(欧几里得,扩展欧几里得,欧拉)

今天考试了,三道题分别是求欧拉,逆欧拉,欧拉求和 对于我这样的蒟蒻来说,我选择狗带. 爆零稳稳的. 现在整理一下: φ(n)(欧拉函数值)为不大于n的正整数中与n互质的数的个数: 有几条这样的性质: 1.欧拉函数是积性函数,但不是完全积性函数,即φ(mn)=φ(n)*φ(m)只在(n,m)=1时成立. 2.对于一个正整数N的素数幂分解N=P1^q1*P2^q2*...*Pn^qn. φ(N)=N*(1-1/P1)*(1-1/P2)*...*(1-1/Pn). 3.除了N=2,φ(N)都是偶数.

欧几里得及扩展欧几里得

欧几里得算法又称辗转相除法,主要用于求两数的最大公约数即gcd(a,b). 欧几里得算法给出gcd(a,b)=gcd(b,a%b)(a>b) 下面我们给出证明: 首先我们设k为gcd(a,b),则a=km,b=kn. 则a%b=a-c*b=km-c*kn=(m-cn)k gcd(b,a%b)=gcd(kn,(m-cn)k) 由于k为a,b的最大公约数,所以n与m-cn互质,所以gcd(b,a%b)=gcd(a,b)=k. 程序实现: 1 int gcd(int a,int b) 2 { 3 if

欧几里得和扩展欧几里得

别人总结的,很详细,http://www.cnblogs.com/frog112111/archive/2012/08/19/2646012.html 欧几里得算法,就是人们常说的辗转相除法,比较好理解,主要作用是求两个数最大公约数,最小公倍数也可方便的求出 1 int gcd(int a,int b) 2 { 3 return b==0?a:gcd(b,a%b); 4 } View Cod 扩展欧几里得就非常神奇了,主要作用是解不定方程, 即  a * x + b * y = c ,我们都知道

欧几里得,扩展欧几里得(模板)

1 int gcd(int a,int b) 2 { 3 return b?gcd(b,a%b):a;//最后返回的a为最大公约数 4 } 扩展欧几里得求逆元:51nod1256 1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 using namespace std; 5 int d,x,y; 6 //ax+by=1(x为a的逆元,同理y为b的逆元) 7 void Exgcd(int

【转】欧几里得与扩展欧几里得

转自:http://www.cnblogs.com/frog112111/archive/2012/08/19/2646012.html 欧几里德算法 欧几里德算法又称辗转相除法,用于计算两个整数a,b的最大公约数. 基本算法:设a=qb+r,其中a,b,q,r都是整数,则gcd(a,b)=gcd(b,r),即gcd(a,b)=gcd(b,a%b). 第一种证明: a可以表示成a = kb + r,则r = a mod b 假设d是a,b的一个公约数,则有 d|a, d|b,而r = a - k

欧几里得与扩展欧几里得算法

欧几里得算法:最大公因数\((gcd)\) 该算法基于: \(gcd(a,b)=gcd(b,a\)%\(b)\) 证明: 令\(a\) % \(b = r\), 则 \(a = k * b + r,\) 因此\(r = a - k * b\) 设\(d\)为\(a,b\)的公约数,那么\(d|a, d|b,\) 则\(a - k * b\) 能被\(d\)整除,即\(d|r\),即\(d|(a\) % \(b)\), 因此\(d\)是\(b\) 和 \((a\) %\(b)\)的公约数, 因此\

hdu 1576 扩展欧几里得

(A/B)%9973=K A/B=K+9973*X A=BK+9973*X*B A%9973=n; BK%9973=n; BK=n+9973*Y (K/n)*B+(-Y/n)*9973=GCD(B,9973)=1; 求出k/n,求出k 1 /* 2 扩展欧几里得 3 扩展欧几里德算法是用来在已知a, b求解一组x,y使得ax+by = Gcd(a, b) =d(解一定存在,根据数论中的相关定理) 4 */ 5 #include<cstdio> 6 #include<iostream>

URAL 1204. Idempotents (扩展欧几里得)

题目链接 题意 : 给你一个同余方程, x*x ≡ x  (mod n),让你求出所有的小于n的x. 思路 : 先来看同余的概念 :给定一个正整数m,如果两个整数a和b满足a-b能被m整除,即m|(a-b),那么就称整数a与b对模m同余,记作a≡b(mod m).对模m同余是整数的一个等价关系. 因此题目中给定的式子可以写成:(x*x-x)/n=k.也就是说(x*x-x)是n的整数倍,取余n是0. 因为n=p*q,而且gcd(p,q)=1 ;所以上式可以写为,x*(x-1)/(p*q)=k. 让

UVa 11768 格点判定(扩展欧几里得求线段整点)

https://vjudge.net/problem/UVA-11768 题意: 给定两个点A(x1,y1)和B(x2,y2),均为0.1的整数倍.统计选段AB穿过多少个整点. 思路: 做了这道题之后对于扩展欧几里得有了全面的了解. 根据两点式公式求出直线 ,那么ax+by=c 中的a.b.c都可以确定下来了. 接下来首先去计算出一组解(x0,y0),因为根据这一组解,你可以写出它的任意解,其中,K取任何整数. 需要注意的是,这个 a' 和 b' 是很重要的,比如说 b' ,它代表的是x每隔 b