【poj2891】同余方程组

同余方程组

例题1pku2891Strange 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 }
【poj2891】

2016-02-02 09:44:06

原文地址:https://www.cnblogs.com/Konjakmoyu/p/5176797.html