Description
人生来就有三个生理周期,分别为体力、感情和智力周期,它们的周期长度为23天、28天和33天。每一个周期中有一天是高峰。在高峰这天,人会在相应的方面表现出色。例如,智力周期的高峰,人会思维敏捷,精力容易高度集中。因为三个周期的周长不同,所以通常三个周期的高峰不会落在同一天。对于每个人,我们想知道何时三个高峰落在同一天。对于每个周期,我们会给出从当前年份的第一天开始,到出现高峰的天数(不一定是第一次高峰出现的时间)。你的任务是给定一个从当年第一天开始数的天数,输出从给定时间开始(不包括给定时间)下一次三个高峰落在同一天的时间(距给定时间的天数)。例如:给定时间为10,下次出现三个高峰同天的时间是12,则输出2(注意这里不是3)。
Input
输入四个整数:p, e, i和d。 p, e, i分别表示体力、情感和智力高峰出现的时间(时间从当年的第一天开始计算)。d 是给定的时间,可能小于p, e, 或 i。 所有给定时间是非负的并且小于365, 所求的时间小于21252。
当p = e = i = d = -1时,输入数据结束。
当p = e = i = d = -1时,输入数据结束。
Output
从给定时间起,下一次三个高峰同天的时间(距离给定时间的天数)。
采用以下格式:
Case 1: the next triple peak occurs in 1234 days.
注意:即使结果是1天,也使用复数形式“days”。
采用以下格式:
Case 1: the next triple peak occurs in 1234 days.
注意:即使结果是1天,也使用复数形式“days”。
Solution
愉快的推一发公式之后我们可以得到以下三个同余方程
$$x equiv p quad (mod;23)$$
$$x equiv e quad (mod;28)$$
$$x equiv i quad (mod;33)$$
中国剩余定理的板子诶
直接 CRT 的板子敲上去然后判一下如果小于 d 的话就一直加余数(23*28*33)直到大于等于 d。
Code
1 #include<cstdio> 2 #define int long long 3 4 int T; 5 int d; 6 int r[5],a[5]; 7 int M=23*28*33; 8 9 int exgcd(int a,int b,int &x,int &y){ 10 if(!b){ 11 x=1;y=0; 12 return a; 13 } 14 int c=exgcd(b,a%b,x,y); 15 int t=x; 16 x=y; 17 y=t-a/b*y; 18 return c; 19 } 20 21 int inv(int a,int b){ 22 int x,y; 23 exgcd(a,b,x,y); 24 return (x%b+b)%b; 25 } 26 27 int CRT(){ 28 int ans=0; 29 for(int i=1;i<=3;i++) 30 (ans+=inv(M/a[i],a[i])*(M/a[i])*r[i])%=M; 31 while(ans<=d) ans+=M; //注意不能是加d 32 //if(ans==d) return 21252-d; 33 return ans-d; 34 } 35 36 signed main(){ 37 a[1]=23,a[2]=28,a[3]=33; 38 while(scanf("%lld%lld%lld%lld",&r[1],&r[2],&r[3],&d)){ 39 if(r[1]==-1) return 0; 40 T++; 41 printf("Case %lld: the next triple peak occurs in %lld days. ",T,CRT()); 42 } 43 }