同余方程组
例题1:pku2891Strange Way to Express Integers
中国剩余定理求的同余方程组mod 的数是两两互素的。然而本题(一般情况,也包括两两互素的情况,所以中国剩余定理成为了“时代的眼泪”)mod的数可能不是互素,所以要转换一下再求。
P=b1(mod a1); P / a1 ==?~~~~b1
P =b2(mod a2);
P =b3(mod a3);
……
P =bn(mod an);
a1~an,b1~bn是给出来的。
解:
第一条:a1*x+b1= P
第二条:a2*y+b2= P
第一条减去第二条: a1*x - a2*y = b2-b1
设A=a1,B=-a2,K=b2-b1,得到了x(实际调用exgcd的时候不理会a2前面的负号)
如果K%d!=0,无解
否则,X=[ (x* K/d)%(B/d)+(B/d) ]%(B/d)
LCU表示最小公倍数
P= a1*X+b1+ 若干倍的LCU(a1,a2)(或者把Y=(K-AX)/B,再P=a2*Y+b2+ 若干倍的LCU(a1,a2)
所以新的b= a1*x+b1,新的a= LCU(a1,a2),
把新的b当成b1,新的a当成a1,再去和a3和b3结合,一直到最后结束,最后新的b就是X
1 #include<cstdio> 2 #include<cstring> 3 #include<cstring> 4 #include<iostream> 5 #include<algorithm> 6 #include<cmath> 7 using namespace std; 8 #define LL long long 9 10 LL a1,b1,a2,b2; 11 12 LL ax,ay; 13 LL exgcd(LL a,LL b) 14 { 15 if(b==0) {ax=1,ay=0;return a;} 16 LL g=exgcd(b,a%b); 17 LL yy=ay; 18 ay=ax-a/b*ay;ax=yy; 19 return g; 20 } 21 22 int main() 23 { 24 freopen("a.in","r",stdin); 25 freopen("a.out","w",stdout); 26 int n; 27 while(scanf("%d",&n)!=EOF) 28 { 29 scanf("%lld%lld",&a1,&b1); 30 bool ok=1; 31 for(int i=2;i<=n;i++) 32 { 33 scanf("%lld%lld",&a2,&b2); 34 if(!ok) continue; 35 LL a,b,c,g; 36 a=a1,b=a2,c=b2-b1; 37 g=exgcd(a,b); 38 if(c%g!=0) {ok=0;continue;} 39 if(b/g<0) b*=-1; 40 ax=((ax*c/g)%(b/g)+(b/g))%(b/g); 41 a=b1+ax*a1; 42 g=a1*a2/exgcd(a1,a2); 43 a1=g;b1=a; 44 } 45 if(!ok) printf("-1 "); 46 else printf("%lld ",b1); 47 } 48 return 0; 49 }
2016-02-02 09:44:06