1. 程式人生 > >擴展歐幾裏得(ex_gcd),中國剩余定理(CRT)講解 有代碼

擴展歐幾裏得(ex_gcd),中國剩余定理(CRT)講解 有代碼

逆元 strong style i++ 擴展歐幾裏得 cin cout ace int

擴展歐幾裏得算法

  求逆元就不說了。

  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 }

擴展歐幾裏得(ex_gcd),中國剩余定理(CRT)講解 有代碼