中国剩余定理模板的返回值是最小值,最小值加上公倍数就是通解,求最小的大于day的通解即为所求
#include<cstdio>//http://poj.org/problem?id=1006
#include<iostream>
using namespace std;
typedef long long ll;
ll exgcd(ll a,ll b,ll &x,ll &y) { //扩展欧几里得算法 ax+by=c 求解a,b
if(!b) {
x=1,y=0;
return a;
}
ll ans=exgcd(b,a%b,x,y);
ll temp=x;
x=y;
y=temp-a/b*y;
return ans;
}
ll inv(ll a,ll p) { //求逆元 ax1(mod p)=>a*x+p*y=1 这里我们求x 要求a与p互质,即gcd(a,p)=1 如果不存在返回-1
ll x,y,gcd;
gcd=exgcd(a,p,x,y);
return (x%p+p)%p;; //x%p+p确保逆元为正数
}
ll china(ll a[],ll b[],int n,int M) { //a[]为除数,b[]为余数,n为有几个除数余数对,M为互质的a[]的最小公倍数,返回值+kM就是全部值
ll y,x=0;
for(int i=0; i<n; ++i) {
ll w=M/a[i];
int t=inv(w,a[i]);//计算逆元
x=(x+w*(b[i]*t))%M;
}
return (x+M)%M;
}
int main() {
ll a[3]= {23,28,33},M=23*28*33;
int T=0;
while(1) {
T++;
int p,e,i,d;
scanf("%d%d%d%d",&p,&e,&i,&d);
if(p==-1) break;
ll b[3]= {p,e,i};
ll ans=china(a,b,3,M);
while(ans<=d) {
ans+=M;
}
printf("Case %d: the next triple peak occurs in %d days.\n",T,ans-d);
}
return 0;
}