Skip to content

POJ - 1006. 生理周期

检测到 KaTeX 加载失败,可能会导致文中的数学公式无法正常渲染。

#题面

#题目描述

人生来就有三个生理周期,分别为体力、感情和智力周期,它们的周期长度为 2323 天、2828 天和 3333 天。每一个周期中有一天是高峰。在高峰这天,人会在相应的方面表现出色。例如,智力周期的高峰,人会思维敏捷,精力容易高度集中。因为三个周期的周长不同,所以通常三个周期的高峰不会落在同一天。对于每个人,我们想知道何时三个高峰落在同一天。对于每个周期,我们会给出从当前年份的第一天开始,到出现高峰的天数(不一定是第一次高峰出现的时间)。你的任务是给定一个从当年第一天开始数的天数,输出从给定时间开始(不包括给定时间)下一次三个高峰落在同一天的时间(距给定时间的天数)。例如:给定时间为 1010,下次出现三个高峰同天的时间是 1212,则输出 22(注意这里不是 33)。

#输入格式

输入四个整数:p,e,i,dp, e, i, d

p,e,ip, e, i 分别表示体力、情感和智力高峰出现的时间(时间从当年的第一天开始计算)。dd 是给定的时间,可能小于 p,e,ip, e, i。 所有给定时间是非负的并且小于 365365,所求的时间小于 2125221252

p=e=i=d=1p = e = i = d = -1 时,输入数据结束。

#输出格式

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

采用以下格式:

Case {}: the next triple peak occurs in {} days.

注意:即使结果是 11 天,也使用复数形式 days。

#输入输出样例

样例输入 #1

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

样例输出 #1

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.

#思路

ss 表示三个峰值同时出现的那一天,TT 为周期,有:

s=p+Tpkp=e+Teke=i+Tiki(1)\tag{1} s = p + T_p k_p = e + T_e k_e = i + T_i k_i

显然需要求出 kp,ke,kik_p, k_e, k_i 使 (1)(1) 式成立,但题目只需要求出 SS 的值,所以可以换一个角度入手。可以将 (1)(1) 式转化为:

{sp( mod 23)se( mod 28)si( mod 33)\left \{ \begin{array}{ll} s \equiv p & (\bmod \ 23) \\ s \equiv e & (\bmod \ 28) \\ s \equiv i & (\bmod \ 33) \\ \end{array} \right.

这样就可以使用中国剩余定理来解决问题了:

  • (28×33×a)1 ( mod 23)(28 \times 33 \times a) \equiv 1 ~(\bmod \ 23),解得 a=6a = 6,则 28×33×a=554428 \times 33 \times a = 5544
  • (23×33×b)1 ( mod 28)(23 \times 33 \times b) \equiv 1 ~(\bmod \ 28),解得 b=19b = 19,则 23×33×b=1442123 \times 33 \times b = 14421
  • (23×28×c)1 ( mod 33)(23 \times 28 \times c) \equiv 1 ~(\bmod \ 33),解得 c=2c = 2,则 23×28×c=128823 \times 28 \times c = 1288

s=5544×p+14421×e+1288×is = 5544 \times p + 14421 \times e + 1288 \times i,则最终结果为 sds - d

#代码

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <iostream>

using std::cin;
using std::cout;
const char endl = '\n';

int t, p, e, i, d;

int gcd(int a, int b) {
return b ? gcd(b, a % b) : a;
}

int lcm(int a, int b) {
return a / gcd(a, b) * b;
}

int main() {
std::ios::sync_with_stdio(false);

while (cin >> p >> e >> i >> d, ~p && ~e && ~i && ~d) {
int l = 21252,
ans = (5544 * p + 14421 * e + 1288 * i - d + l) % l;
cout << "Case " << ++t << ": the next triple peak occurs in " << (ans ? ans : l) << " days." << endl;
}

return 0;
}