中国剩余定理
#include<iostream> //POJ 1006 Biorhythms
using namespace std;
int x,y,q;
void extend_eluid(int a,int b) //扩展欧几里德算法
{
if(b==0)
{
x=1;y=0;q=a;
}
else
{
extend_eluid(b,a%b);
int temp=x;
x=y;y=temp-a/b*y;
}
}
//23,28,33两两互素
int main()
{
int A1,A2,A3,T,p,e,i,d,peak,cases=0;
extend_eluid(28*33,23);
A1=28*33*x;
extend_eluid(23*33,28);
A2=23*33*x;
extend_eluid(23*28,33);
A3=23*28*x;
T=23*28*33;
while(cin>>p>>e>>i>>d&&p!=-1)
{
peak=A1*p+A2*e+A3*i-d;
peak=(peak%T+T)%T;
if(peak==0)
peak=T;
printf("Case %d: the next triple peak occurs in %d days.\n", ++cases,peak);
}
return 0;
}
//比如输入5,20,34,即求一个数 M 满足
// M = 5 + 23 * P1 = 20 + 28 * P2 = 34 + 33 * P3; (P1,P2,P3,都为整数)
//化为M≡5(mod 23)≡20(mod 28)≡34(mod 33) ,求线性同余方程组
//这里算出来M是19900,19900%33=1,与≡34(mod 33)其实是一样的
/*
对于一般情形:(w[1],w[2]...w[n]是两两互素的正整数)
a=b[1] (mod w[1])
a=b[2] (mod w[2])
.....
a=b[n] (mod w[n])
求解 a
令WS=w[1]*w[2]*...w[n],用AW[i]=WS/w[i],显然 gcd(AW[i],w[i])=1,
由扩展欧几里德定理,存在两整数p[i],q[i],满足 AW[i] * p[i] + w[i] * q[i] = 1;
如果记 e[i] = AW[i] * p[i] ,即 e[i] = 1- w[i] * q[i];
则(1)当j!=i时,由于 e[i]=AW[i]*p[i],因为 AW[i]%w[j] =0,所以 e[i]=0 (mod w[j]),
(2)当j=i时,由于 e[i]=1- w[i] * q[i], 所以 e[i]=1 (mod w[j]);
所以 e[1]*b[1]+e[2]*b[2]+...+e[k]*b[k] 就是 a 的一个解,
而加减 WS倍后就可以得到最小非负整数解了
*/