[POJ 1006] Menstrual Cycle

Description

Humans are born with three physiological cycles, namely physical, emotional and intellectual cycles, and their cycle lengths are 23 days, 28 days and 33 days. One day in each cycle is the peak. On the peak day, people will excel in the corresponding areas. For example, at the peak of the intellectual cycle, people will have quick thinking and high concentration of energy. Because the perimeters of the three cycles are different, usually the peaks of the three cycles do not fall on the same day. For everyone, we want to know when the three peaks fall on the same day. For each period, we give the number of days from the first day of the current year to the peak (not necessarily the time of the first peak). Your task is to give a number of days starting from the first day of the current year, output the time (days from the given time) when the next three peaks fall on the same day starting from the given time (excluding the given time). For example: Given time is 10, and the next time when three peaks occur on the same day is 12, output 2 (note that it is not 3 here).

Input

Enter four integers: p, e, i and d. p, e, i represent the time of peak physical, emotional, and intellectual peaks, respectively (the time starts from the first day of the year). d is a given time and may be less than p, e, or i. All given times are non-negative and less than 365, the time sought is less than 21252.
The input data ends when p = e = i = d = -1.

Output

From the given time, the time of the next three peaks on the same day (days from the given time).
Use the following format:
Case 1: the next triple peak occurs in 1234 days.
Note: Use the plural form "days" even if the result is 1 day.

Solution

After happily pushing the formula, we can get the following three congruence equations

$$x \equiv p \quad (mod\;23)$$

$$x \equiv e \quad (mod\;28)$$

$$x \equiv i \quad (mod\;33)$$

The board of the Chinese remainder theorem

Knock on the CRT board directly and judge that if it is less than d, add the remainder (23*28*33) until it is greater than or equal to 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.\n",T,CRT());
42     }
43 }

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324872655&siteId=291194637