题意:已知(n+d)%23=p; (n+d)%28=e; (n+d)%33=i ,求n 。
解题思路:模板题
tp=((tp-d)%M+M)%M;讲一下意义吧。(tp-d)%M距离d最近的差,再加上一个M,因为(x=x0+k*M)
#include<cstdio>
#include<cstring>
#include<iostream>
#define ll long long
using namespace std;
ll a[3]={23,28,33},b[3],M;
int n;
/*该方程 用于以下形式
x=b1(mod a1)
x=b2(mod a2)
......
x=bn(mod an)*/
ll ex_gcd(ll a,ll b,ll &x,ll &y)
{
if(b==0){x=1,y=0;return a;}
ll r=ex_gcd(b,a%b,y,x);
y-=x*(a/b);
return r;
}
ll ex_crt()
{
M=a[0];
ll R=b[0],x,y,d;//a是除数,也是答案 。b是被除的
for(int i=1;i<3;i++)
{
d=ex_gcd(M,a[i],x,y);
if((b[i]-R)%d) return -1;//无解
x=(b[i]-R)/d*x%(a[i]/d);//计算系数
R+=x*M;//计算新X1的a,即特解
M=M/d*a[i];//LCM新的最小公倍数
R%=M;//由方程的原始形式可知,可以这么做。而且可以减小数字大小
}
return R>0? R: R+M;
}
int main()
{
//freopen("t.txt","r",stdin);
ll d;
int cnt=1;
while(scanf("%lld%lld%lld%lld",&b[0],&b[1],&b[2],&d)!=EOF)
{
if(b[0]==-1) break;
ll tp=ex_crt();
tp=((tp-d)%M+M)%M;
if(tp==0) tp=M;
printf("Case %d: the next triple peak occurs in %lld days.\n",cnt++,tp);
}
return 0;
}