数论之扩展欧几里德

扩展欧几里德首先要提到的是裴蜀定理:

  设 gcd(a,b)=c,则对于任意实数 x,y 有 c|ax+by 成立

  特别的,一定存在 x,y 满足 ax+by=c

  推论:a,b 互质等价于 ax+by=1 有解。

  求解 x,y:

  设 a>b。

  (1) 当 a mod b =0 时,gcd(a,b)=b。此时 x=0,y=1。

    因为 0*a+1*b=b

  (2) 当 a mod b!=0 时

  设 ax1+by1=gcd(a,b),bx2+(a mod b)y2=gcd(b,a mod b);

  据欧几里德原理有:ax1+by1=bx2+(a mod b)y2;

  因为   a mod b=a-(a/b)*b;

  则有:ax1+by1=bx2+(a-a(a/b)*b)y2

  根据恒等原理有: x1=y2,y1=x2-(a/b)*y2;

  于是我们便有了代码:

 1 #include <cstdio>
 2 using namespace std;
 3 long long a,b,x,y;
 4 
 5 void exgcd(long long a,long long b,long long &x,long long &y)
 6 {
 7     if(a%b==0)
 8     {
 9         x=0;y=1;return ;
10     }
11     exgcd(b,a%b,x,y);
12     long long t=x;
13     x=y;y=t-(a/b)*y;
14 }
15 
16 int main()
17 {
18     scanf("%lld%lld",&a,&b);
19     exgcd(a,b,x,y);
20     printf("%lld%lld",x,y);
21     return 0;
22 }
View Code

  其实,这个代码还有个压缩版本:

 1 #include <cstdio>
 2 using namespace std;
 3 long long a,b,x,y;
 4 
 5 void exgcd(long long a,long long b,long long &x,long long &y)
 6 {
 7     if(a%b==0)
 8     {
 9         x=0;y=1;return ;
10     }
11     exgcd(b,a%b,y,x);        //注意了, y 在前, x 在后 
12     y-=x*(a/b); 
13 }
14 
15 int main()
16 {
17     scanf("%lld%lld",&a,&b);
18     exgcd(a,b,x,y);
19     printf("%lld%lld",x,y);
20     return 0;
21 }
View Code

扩展欧几里德可以用来解二元一次不定方程

  例如:不定方程ax+by=d

  设 c=gcd(a,b);

  先用扩欧解出 ax+by=c 的解 x0,y0

  x0=x0*d/c; y0=y0*d/c。

  x,y的通解为

            x=x0+b/c*t;

            y=y0+a/c*t;

  不定方程 ax+by=d 有整数解的条件:

            d mod gcd(a,b)==0

  求解 x 的最小非负整数解:

 1 #include <cstdio>
 2 using namespace std;
 3 long long a,b,c,d,x0,y0,x;
 4 
 5 long long gcd(long long x,long long y)
 6 {
 7     return (x%y==0)?y:gcd(y,x%y);
 8 }
 9 
10 void exgcd(long long a,long long b,long long &x,long long &y)
11 {
12     if(a%b==0)
13     {
14         x=0;y=1;return ;
15     }
16     exgcd(b,a%b,y,x);
17     y-=x*(a/b); 
18 }
19 
20 int main()
21 {
22     scanf("%lld%lld%lld",&a,&b,&d);
23     c=gcd(a,b);
24     if(d%c)
25     {
26         puts("No solution.");return 0;
27     }
28     a/=c;b/=c;d/=c;
29     exgcd(a,b,x0,y0);
30     x=x0%b;
31     while(x<0)x+=b;
32     printf("%lld",x);
33     return 0;
34 }
View Code

  例题:poj 1061 青蛙的约会

posted @ 2019-01-23 11:07  __Michael  阅读(296)  评论(0编辑  收藏  举报