poj 1006(中国剩余定理+模板题)

题意:人自出生起就有体力,情感和智力三个生理周期,分别为23,28和33天。一个周期内有一天为峰值,在这一天,人在对应的方面(体力,情感或智力)表现最好。通常这三个周期的峰值不会是同一天。现在给出三个日期,分别对应于体力,情感,智力出现峰值的日期。然后再给出一个起始日期,要求从这一天开始,算出最少再过多少天后三个峰值同时出现。

设第x天同时出现,则x%23=p%23,x%28=i%28...(等于p,i也是可以的,计算中会mod),然后用x-d即可,因为x可能小于d,所以加上23*28*33再对这个数取模。

 1 #include<iostream>
 2 #include<string.h>
 3 #include<string>
 4 #include<sstream>
 5 #include<vector>
 6 #include<deque>
 7 #include<map>
 8 #include<algorithm>
 9 #include<iomanip>
10 #include<math.h>
11 #include<set>
12 using namespace std;
13 
14 typedef long long ll;
15 typedef unsigned long long ull;
16 const int mod = 1000000007;
17 
18 //扩展欧几里得求逆元
19 ll exgcd(ll &x,ll &y,ll a,ll b)
20 {
21     if (b == 0)
22     {
23         x = 1;
24         y = 0;
25         return a;
26     }
27     ll r = exgcd(x, y, b, a%b);
28     ll temp = x;
29     x = y;
30     y = temp - a / b * y;
31     return r;
32 }
33 
34 ll inv(ll a,ll b)
35 {
36     ll x, y;
37     ll g = exgcd(x, y, a, b);
38     if (g == 1)
39     {
40         return (x%b + b) % b;
41     }
42     else
43         return -1;
44 }
45 
46 ll china(ll *n, ll *m,ll len)
47 {
48     ll M = 1;
49     ll res = 0;
50     for (int i = 0; i < len; i++)
51         M = M * m[i];
52     for (int i = 0; i < len; i++)
53     {
54         ll t = M / m[i];
55         res = (res + t * inv(t, m[i])*n[i]) % M;
56     }
57     return (res+M)%M; //防止res为负数(不太懂)
58 }
59 
60 int main()
61 {
62     int cas = 1;
63     int p, e, i, d;
64     ll m[3] = {23,28,33}, n[3];
65     while (cin  >> e >> i >> d>>p && p != -1)
66     {
67         n[0] = e % 23;
68         n[1] = i % 28;
69         n[2] = d % 33;
70         ll  ans = (china(n, m, 3)-p+21252)%21252;
71         ans = ans ? ans : 21252;
72         cout << "Case " << cas++ << ": the next triple peak occurs in " << ans << " days." << endl;
73     }
74     return 0;
75 }

猜你喜欢

转载自www.cnblogs.com/QingFengDaHui/p/10392435.html