擴展歐幾裏得(ex_gcd),中國剩余定理(CRT)講解 有代碼
阿新 • • 發佈:2018-03-08
逆元 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],(k∈Z)}
然後轉化為%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 returna; 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)講解 有代碼