标签:中国剩余定理 pen 因此 gcd family lld lse for util
题意很明确,这里的模数是不互质的,因此不能直接套中国剩余定理.这里稍微讲一下中国剩余定理的扩展,假设前i个方程的特解为ans(i),通解为x(i)=ans(i)+k*lcm(前i个模数).把x(i)代入到第i+1个方程,用扩展欧几里得定理求解k=k0,ans(i+1)=ans(i)+k0*lcm(前i个模数),则x(i+1)=ans(i+1)+lcm(前i+1个模数).大概思路就是这样,但有些细节需要注意一下,求出来的k0,ans(i+1)需要用求模的方法缩小一下.
1 #include <cstdio> 2 #include <cstdlib> 3 #include <iostream> 4 #include <algorithm> 5 #include <utility> 6 #include <ctime> 7 #include <cmath> 8 #include <cstring> 9 #include <string> 10 #include <stack> 11 #include <queue> 12 #include <vector> 13 #include <set> 14 #include <map> 15 16 using namespace std; 17 typedef unsigned long long ULL; 18 typedef __int64 LL; 19 typedef long double LB; 20 const int INF_INT=0x3f3f3f3f; 21 const LL INF_LL=0x3f3f3f3f3f3f3f3f; 22 23 vector<LL> a,m; 24 25 LL exgcd(LL a,LL b,LL &x,LL &y) 26 { 27 if(!b) 28 { 29 x=1,y=0; 30 return a; 31 } 32 LL g=exgcd(b,a%b,y,x); //简化写法 33 y-=a/b*x; //y从下一个方程回溯回来时是下一个方程的x 34 return g; 35 } 36 37 LL solve(LL n) 38 { 39 LL ans=0,lcm=1,x,y; 40 for(int i=0;i<n;i++) 41 { 42 if(!i) ans=a[i],lcm*=m[i]; 43 else 44 { 45 LL g=exgcd(lcm,m[i],x,y),c=a[i]-ans; 46 if(c%g) 47 { 48 ans=-1; 49 break; 50 } 51 x*=c/g; 52 LL t=m[i]/g; 53 x=(x%t+t)%t; 54 ans+=x*lcm; 55 lcm*=m[i]/g; 56 ans=((ans%lcm)+lcm)%lcm; 57 } 58 } 59 return ans; 60 } 61 62 int main() 63 { 64 // freopen("std.in","r",stdin); 65 // freopen("std.out","w",stdout); 66 LL k; 67 while(~scanf("%lld",&k)) 68 { 69 m.clear(),a.clear(); 70 LL x,y; 71 for(int i=0;i<k;i++) scanf("%lld %lld",&x,&y),m.push_back(x),a.push_back(y); 72 printf("%lld\n",solve(k)); 73 } 74 return 0; 75 }
Strange Way to Express Integers POJ 2891(中国剩余定理扩展)
标签:中国剩余定理 pen 因此 gcd family lld lse for util
原文地址:https://www.cnblogs.com/VBEL/p/11437896.html