3.2 生理周期
Note:读题懵,看了书上的解题方法更懵。
能用简单枚举或跳步枚举是因为,周期长度为23 28 33三数最小公倍数为三数相乘。相当于是一个极为特殊的数,但一般情况下并不能用这样的方法。
经查阅 该类题正规的解法为数论中的《中国剩余定理》应用。
附几篇就此定理的解释,待理解。
https://blog.csdn.net/qq_35747066/article/details/78111333
https://blog.csdn.net/tick_tock97/article/details/71313058
https://blog.csdn.net/destiny1507/article/details/81751168
问题描述:
人生来就有三个生理周期,分别为体力周期、情感周期和智力周期,它们的周期长度分别为23天,28天和33天。每一个周期中有一天是高峰。在高峰这一天,人会在相应的方面表现出色。例如,在治理周期的高峰,人会思维敏捷,注意力容易高度集中。因为三个周期的长度不同,所以通常三个周期的高峰不会在同一天。对于每个人,想知道何时三个高峰在同一天。对于每个周期,会给出从当前年份的第一天开始到出现高峰的天数(不一定是第一次出现高峰的时间)。给定一个从当年第一天开始的天数,你的任务是输出从给定时间开始(不包括给定时间),下一次三个高峰在同一天的时间(距给定时间的天数)。例如,给定时间为10,下次出现三个高峰同一天的时间是12,则输出2(注意这里不是3)。
输入数据:
输入包含多组数据,每一组数据由4个整数组成,数据以-1 -1 -1 -1 结束。
4个整数 (p,e,i,d)分别表示(给定时间到体力,情感,智力高峰出现的天数;给定时间)。
所有时间是非负的并且小于或等于365,所求时间小于或等于21252。
输入样例:
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
输出样例:
Case1: the next triple peak occurs in 21252 days.
Case2: the next triple peak occurs in 21152 days.
Case3: the next triple peak occurs in 19575 days.
Case4: the next triple peak occurs in 16994 days.
Case5: the next triple peak occurs in 8910 days.
Case6: the next triple peak occurs in 10789 days.
解题思路:
解法1(暴力):从给定的时间开始,遍历到21252,找到最早出现的某一天,在这一天体力、情感和智力高峰均出现,即满足
(j-p)%23==0、(j-e)%33==0、(j-i)%33==0
解法2:检索时可以利用已经发现的高峰值来加速搜索过程。例如,若发现第102天是体力的高峰值,那么第103,104,105...124天都不可能是体力、情感和智力高峰均出现的时间,因此可以直接跳到第102+23 = 125天。这个优化策略可以概括为:若某项高峰值的时间已经出现,则该高峰值的出现周期可以作为搜索步长。
#include<cstdio>
#include<stdlib.h>
#include<iostream>
using namespace std;
int main(){
int j, count=0;
int p, e, i, d;
cin >> p >> e >> i >> d;
while(p != -1){
count++;
for(j = d+1; j < 21252; j++)//枚举每一天找到体力高峰
if((j-p)%23==0) //找到体力高峰
break;
for(; j < 21252; j = j + 23)//每隔23天一个体力高峰,枚举体力高峰
if((j-e)%28==0)
break; //找到情感高峰
for(; j < 21252; j = j + 23*28)//每隔23*28天一个公共高峰,枚举每一个公共高峰
if((j-i)%33==0)
break; //找到三个周期的公共高峰
printf("Case %d:the next triple peak occurs in %d days.\n", count, j-d);
cin >> p >> e >> i >> d;
}
system("pause");
return 0;
}