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”。
Sample Input
0 0 0 0 0 0 0 100 5 20 34 325 4 5 6 7 283 102 23 320 203 301 203 40 -1 -1 -1 -1
Sample Output
Case 1: the next triple peak occurs in 21252 days. Case 2: the next triple peak occurs in 21152 days. Case 3: the next triple peak occurs in 19575 days. Case 4: the next triple peak occurs in 16994 days. Case 5: the next triple peak occurs in 8910 days. Case 6: the next triple peak occurs in 10789 days.
Hint
Translator
北京大學程序設計實習2007, Xie Di
題意如題。
題解:現設 num 是下一個相同日子距離開始的天數?p,e,i,d 如題中所設!那么就可以得到三個式子:
( num + d ) % 23 == p;
( num + d ) % 28 == e;
( num + d ) % 33 == i;
這是典型的中國剩余定理問題:傳送門。
以上是互質的中國剩余定理,比較好理解,還有非互質的中國剩余定理,存在無解情況:傳送門。
給出兩種代碼,第一種包含了運算過程,適用于其他數據,第二種是該題的成品。
代碼一:
#include <iostream> #include <cstdio> using namespace std; #define mod 21252 int exgcd(int a,int b,int &x,int &y) //計算擴展歐幾里得 {if(b==0) {x=1;y=0;return a;}int d=exgcd(b,a%b,y,x); y-=a/b*x;return d; } int inv(int a,int n) //計算逆元 {int d,x,y;d=exgcd(a,n,x,y);if(d==1) return (x%n+n)%n;else return -1; } int datain[5]={23,28,33}; int dataout[5]; void cal() //計算中國剩余定理 {int ans=1;for(int i=0;i<3;i++)ans*=datain[i];for(int i=0;i<3;i++){ans/=datain[i];dataout[i]=inv(ans,datain[i])*ans; //記得結果算出來ans*=datain[i]; //記得乘回來 } } int main() {cal();//for(int i=0;i<3;i++)// cout<<dataout[i]<<endl;int p,e,i,d,cas=1,ans;while(cin>>p>>e>>i>>d){if(p==-1&&e==-1&&i==-1&&d==-1)break;ans=(dataout[0]*p+dataout[1]*e+dataout[2]*i-d+mod)%mod;if(!ans) ans=mod;printf("Case %d: the next triple peak occurs in %d days.\n",cas++,ans);}return 0; }
代碼二:
#include <iostream> #include <cstdio> using namespace std; #define mod 21252 int main() {int p,e,i,d,cas=1,ans;while(cin>>p>>e>>i>>d){if(p==-1&&e==-1&&i==-1&&d==-1)break;ans=(5544*p+14421*e+1288*i-d+mod)%mod;if(!ans) ans=mod;printf("Case %d: the next triple peak occurs in %d days.\n",cas++,ans);}return 0; }