题意
题目的意思大概是说,人的体力,情感和智力有三个不同的生理周期,分别为23,28和33天,每隔一个周期会达到峰值。现在给出三个日期,分别对应于体力,情感,智力出现峰值的周期。然后再给出一个起始日期,要求从这一天开始,算出最少再过多少天后三个峰值同时出现。
分析
看上去计算比较大,实际上这是一道数学题,牵涉到剩余定理。
剩余定理:
在《孙子算经》中有这样一个问题:“今有物不知其数,三三数之剩二(除以3余2),五五数之剩三(除以5余3),七七数之剩二(除以7余2),问物几何?”这个问题称为“孙子问题”,该问题的一般解法国际上称为“中国剩余定理”。具体解法分三步:
1、找出三个数:从3和5的公倍数中找出被7除余1的最小数15,从3和7的公倍数中找出被5除余1 的最小数21,最后从5和7的公倍数中找出除3余1的最小数70。
2、用15乘以2(2为最终结果除以7的余数),用21乘以3(3为最终结果除以5的余数),同理,用70乘以2(2为最终结果除以3的余数),然后把三个乘积相加(15*2+21*3+70*2)得到和233。
3、用233除以3,5,7三个数的最小公倍数105,得到余数23,这个余数23就是符合条件的最小数。
因此,
23 * 28 % 33 = 17, 可知 2 * (23 * 28) % 33 = 34,34 % 33 = 1。因此33的key为2 * 23 * 28 = 1288。
23 * 33 % 28 = 3,可知19 * (23 * 33) % 28 = 57, 57 % 28 = 1。因此28的key为19 * 23 * 33 = 14421。
28 * 33 % 23 = 4,可知6 * (28 * 33) % 23 = 24, 24 % 23 = 1。因此23的key为6 * 28 * 33 = 5544。
弄明白以后就很简单了,代码如下:
Memory: 228K Time: 16MS Length:19LINES
#include<iostream>
using namespace std;
int main()
{
const int k1 = 5544;
const int k2 = 14421;
const int k3 = 1288;
int temp1, temp2, temp3, temp4;
int cnt = 0;
while (fscanf(stdin, "%d%d%d%d", &temp1, &temp2, &temp3, &temp4) && temp1 != -1)
{
int temp = (k1 * temp1 + k2 * temp2 + k3 * temp3) % 21252 - temp4;
if (temp <= 0)
temp += 21252;
cout << "Case " << ++cnt << ": the next triple peak occurs in "
<< temp << " days." << endl;
}
return 0;
}