- #include <iostream>
- int a[4];
- int m[4];
- int M,x,y,gcd;
- void Extend_Euclid(int a,int b)
- {
- if(b==0)
- {
- x=1;
- y=0;
- return;
- }
- Extend_Euclid(b,a%b);
- int temp=x;
- x=y;
- y=temp-(a/b)*y;
- }
- int RemindChina(int r)
- {
- M=1;
- int Mi,i,ans=0;
- for(i=1;i<=r;i++)
- M*=m[i];
- for(i=1;i<=r;i++)
- {
- Mi=M/m[i];
- Extend_Euclid(Mi,m[i]);
- ans=(ans+Mi*x*a[i])%M;
- }
- if(ans<0)
- ans+=M;
- return ans;
- }
- int main()
- {
- int p,e,i,d,t=1;
- while(std::cin>>p>>e>>i>>d)
- {
- if(p==-1&&e==-1&&i==-1&&d==-1)
- break;
- a[1]=p;a[2]=e;a[3]=i;
- m[1]=23;m[2]=28;m[3]=33;
- int ans=RemindChina(3);
- if(ans<=d)
- ans+=21252;
- std::cout<<"Case "<<t++<<": the next triple peak occurs in "<<ans-d<<" days."<<std::endl;
- }
- return 0;
- }
-
广义的中国剩余定理
对于方程x≡a[i] (mod m[i])中m[i]与m[j]不互素,怎样求x?
中国剩余定理中求同余方程组的模数都是两两互质的,但是这个题目里面可能不是两两互质,所以需要转换一下
1)x=b1(mod a1);
2)x=b2(mod a2);
a1*x1+b1=x=b2(mod a2)
所以a1*x1+b1=b2(mod a2)
a1*x1=(b2-b1)(mod a2)
形如AX==B(mod p)的同余式可用扩张欧几里德算法求出一个最小的一个X。所以容易求出x1的值,代入1)式,得出x.
接着这一步很关键的是将该两个方程合并成一个方程:xx=x(mod lcm(a1,a2) );
主要用了合并的思想
设x≡ r1 mod a1 x ≡ r2 mod a2
则可以通过等式转换为一个等式x≡r mod a,然后一直合并下去,最终只有一个同余方程式。
- #include <iostream>
- #include <cstdio>
- #include <string.h>
- using namespace std;
- #define LL long long
- const int N = 1010;
- LL gcd(LL a,LL b)
- {
- return b? gcd(b,a%b):a;
- }
- void extend_Euclid(LL a,LL b,LL &x,LL &y)
- {
- if(b==0)
- {
- x = 1;
- y = 0;
- return;
- }
- extend_Euclid(b,a%b,x,y);
- LL temp=x;
- x=y;
- y=temp-a/b*y;
- }
- LL inv(LL a,LL b)
- {
- LL d = gcd(a,b);
- if(d != 1)
- return -1;
- LL x,y;
- extend_Euclid(a,b,x,y);
- return (x % b + b) % b;
- }
- bool merge(LL a1,LL r1,LL a2,LL r2,LL &a3,LL &r3)
- {
- LL d = gcd(a1,a2);
- LL c = r2 - r1;
- if(c % d)
- return false;
- c = (c % a2 + a2) % a2;
- a1 /= d;
- a2 /= d;
- c /= d;
- c *= inv(a1,a2);
- c %= a2;
- c *= (a1*d);
- c += r1;
- a3 = a1 * a2 * d;
- r3 = (c % a3 + a3) % a3;
- return true;
- }
- LL China_Remain(LL n,LL a[],LL r[])
- {
- LL a1 = a[1],r1 = r[1];
- for(LL i = 2;i <= n;i++)
- {
- LL a2,r2,a3,r3;
- a2 = a[i];
- r2 = r[i];
- if(!merge(a1,r1,a2,r2,a3,r3))
- {
- return -1;
- }
- a1 = a3;
- r1 = r3;
- }
- return (r1%a1+a1)%a1;
- }
- int main()
- {
- LL i, n;
- LL a[N],r[N];
- while(~scanf("%I64d",&n))
- {
- memset(a,0,sizeof(a));
- memset(r,0,sizeof(r));
- for(i = 1;i <= n;++i)
- scanf("%I64d%I64d",&a[i],&r[i]);
- LL ans = China_Remain(n,a,r);
- printf("%I64d\n",ans);
- }
- return 0;
- }