扩展欧几里得(ex_gcd),中国剩余定理(CRT)讲解 有代码

扩展欧几里得算法

  求逆元就不说了。

  ax+by=c

  这个怎么求,很好推。

  设d=gcd(a,b) 满足d|c方程有解,否则无解。

  扩展欧几里得求出来的解是 x是 ax+by=gcd(a,b)的解。

  对于c的话只需要x*c/gcd(a,b)%(b/d)即可,因为b/d的剩余系更小。

  为什么这样呢?

  设a'=a/d,b'=b/d 求出a'x+b'y=1的解,两边同时乘d,然后x也是ax+by=d的解,

  然后因为b'的剩余系更小,所以%b’

中国剩余定理是合并线性方程组的

中国余数定理

  转化为一个线性方程 ax+by=c

   a,b

   c,d

   num % a=b;

   num % c=d;

   求num最小正整数解;

   num=ax+b=cy+d

   ax-cy=d-b

   可以化为求解 ax(d-b)(mod c);

   ax+cy=d-b

   用ex_gcd求解出x;

   num=a*x+b;

   这样num mod a=b

   num mod c=d-b+b=d

   因为x为最小正整数解,所以num为最小解

   满足的集合为{x|x=num+k·[a,b],(kZ)}

   然后转化为%lcm(a,c)=num

   然后继续合并

附上代码,完美代码

 

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<iostream>
 4 #include<cmath>
 5 typedef long long ll;
 6 using namespace std;
 7 ll ex_gcd(ll a,ll b,ll &x,ll &y)
 8 {
 9     if (!b)
10     {
11         x=1,y=0;
12         return a;
13     }
14     ll fzy=ex_gcd(b,a%b,x,y);
15     ll t=x;
16     x=y;y=t-a/b*y;
17     return fzy;
18 }
19 int main()
20 {
21     int t;
22     ll z1,z2,z3,z4;
23     while (cin>>t)
24     {
25         bool flag=0;
26         scanf("%lld%lld",&z1,&z2);
27         for (int i=1;i<t;i++)
28         {
29             scanf("%lld%lld",&z3,&z4);
30             if (flag) continue;
31             ll a=z1,b=z3,c=z4-z2;
32             ll x,y;
33             ll d=ex_gcd(a,b,x,y);
34             if (c%d!=0)
35             {
36                 flag=1;
37                 continue;
38             }
39             ll t=b/d;
40             x=(x*(c/d)%t+t)%t;//t的剩余系更小。
41             z2=z1*x+z2;//得出num
42             z1=z1*(z3/d);
43             cout<<"z1="<<z1<<" z2="<<z2<<endl;
44         }
45         if (flag==1) cout<<-1<<endl;
46         else cout<<z2<<endl;
47     }
48 }

 

posted @ 2018-03-07 20:35  Kaiser-  阅读(672)  评论(0编辑  收藏  举报