生理周期

Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 133189   Accepted: 42577

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时,输入数据结束。

Output

从给定时间起,下一次三个高峰同天的时间(距离给定时间的天数)。

采用以下格式:
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.

Source

Translator

北京大学程序设计实习2007, Xie Di
 
分析:
看到这个题目,三个时间互质,好像没有什么快捷方法,就先尝试暴力破解了。
暴力破解写了3次:
设下一次巅峰时刻分别为p+23*j,i+33*m,e+28*k。
1. j++,m++,k++,直到找到三个数字相等的时刻就是全盛时期。测试数据都过了,但是。。。超时了。
2. 题目要求了,时间不能超过21252天,所以,从d+1开始到21252遍历,找到(ans-p)%23==0 && (ans-e)%28==0 && (ans-i)%33==0时候,就是答案了。耗时250ms。
3. 对2做了点小优化,不再是从d+1到21252一个一个遍历,而是改为,从i+33开始以33为步长进行遍历。耗时110ms。
 
这个题目也可以用“中国剩余定理”,传说中的韩信点兵啊,具体见http://blog.csdn.net/bo_jwolf/article/details/9355937
 
第一次:
 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 
 4 #define SUCCESS 1
 5 #define FAILURE 0
 6 
 7 int p = 0;
 8 int e = 0;
 9 int i = 0;
10 int d = 0;
11 
12 int Search(int j, int M, int *inm, int i)
13 {
14     int m = *inm;
15     int result = FAILURE;
16     while(1)
17     {
18         if(p+23*j == i+M*m)
19         {
20             result = SUCCESS;
21             break;
22         }
23         else if(p+23*j > i+M*m)
24             m++;
25         else if(p+23*j < i+M*m)
26         {
27             m = 0;
28             result = FAILURE;
29             break;
30         }
31     }
32     *inm = m;
33     return result;
34 }
35 
36 int Match(int *j, int *k, int *m)
37 {
38     while(*j<65534)
39     {
40         if(SUCCESS == Search(*j,33,m,i))
41         {
42             if(SUCCESS == Search(*j,28,k,e))
43                 return SUCCESS;
44         }
45 
46         (*j)++;
47     }
48     return FAILURE;
49 }
50 
51 int main(void)
52 {
53     int j = 1;
54     int k = 1;
55     int m = 1;
56     int ans = 0;
57     int n = 0;
58     while(4==scanf("%d %d %d %d", &p, &e, &i, &d) && (p!=-1 || e!=-1 || i!=-1 || d!=-1))
59     {
60         getchar();
61         n++;
62         p = p % 23;
63         e = e % 28;
64         i = i % 33;
65 
66         Match(&j,&k,&m);
67 
68         ans = p+23*j;
69 
70         if(ans < d)
71             ans = 21252 + ans - d;
72         else
73             ans = ans -d;
74 
75         if(ans%21252 > d)
76             ans %= 21252;
77 
78         printf("Case %d: the next triple peak occurs in %d days.\n", n, ans);
79     }
80     return 0;
81 }
View Code

第二次:

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 
 4 int p = 0;
 5 int e = 0;
 6 int i = 0;
 7 int d = 0;
 8 
 9 int main(void)
10 {
11     int ans = 0;
12     int n = 0;
13     while(4==scanf("%d %d %d %d", &p, &e, &i, &d) && (p!=-1 || e!=-1 || i!=-1 || d!=-1))
14     {
15         getchar();
16         n++;
17         p = p % 23;
18         e = e % 28;
19         i = i % 33;
20 
21         for(ans=d+1;;ans++)
22         {
23             if((ans-p)%23==0 && (ans-e)%28==0 && (ans-i)%33==0)
24             {
25                 break;
26             }
27         }
28 
29         if(ans < d)
30             ans = 21252 + ans - d;
31         else
32             ans = ans - d;
33 
34         if(ans%21252 > d)
35             ans %= 21252;
36 
37         printf("Case %d: the next triple peak occurs in %d days.\n", n, ans);
38     }
39     return 0;
40 }
View Code

第三次:

 1 #include <stdio.h>
 2 
 3 int p = 0;
 4 int e = 0;
 5 int i = 0;
 6 int d = 0;
 7 
 8 int main(void)
 9 {
10     int ans = 0;
11     int n = 0;
12     int flag = 0;
13     while(4==scanf("%d %d %d %d", &p, &e, &i, &d) && (p!=-1 || e!=-1 || i!=-1 || d!=-1))
14     {
15         getchar();
16         p = p % 23;
17         e = e % 28;
18         i = i % 33;
19         ans = i+33;
20         flag = 1;
21 
22         if(p==e && e==i && p>d)
23         {
24             ans=p-d;
25             flag=0;
26         }
27         if(p==e && e==i && p<=d)
28         {
29             ans=p+21252-d;
30             flag=0;
31         }
32 
33         if(flag)
34         {
35             while(((ans-p)%23)!=0||((ans-e)%28)!=0||ans-d<0)
36                 ans+=33;
37             ans -= d;
38         }
39 
40         printf("Case %d: the next triple peak occurs in %d days.\n", ++n, ans);
41     }
42     return 0;
43 }
View Code