您的位置:首页 > 其它

POJ1006 Biorhythms 解题报告

2011-05-17 18:49 281 查看
Biorhythms
Time Limit: 1000MS Memory Limit: 10000K
题目描述:
Description
人生来就有三个生理周期,分别为体力、感情和智力周期,它们的周期长度为23天、28天和33天。每一个周期中有一天是高峰。在高峰这天,人会在相应的方面表现出色。例如,智力周期的高峰,人会思维敏捷,精力容易高度集中。因为三个周期的周长不同,所以通常三个周期的高峰不会落在同一天。对于每个人,我们想知道何时三个高峰落在同一天。对于每个周期,我们会给出从当前年份的第一天开始,到出现高峰的天数(不一定是第一次高峰出现的时间)。你的任务是给定一个从当年第一天开始数的天数,输出从给定时间开始(不包括给定时间)下一次三个高峰落在同一天的时间(距给定时间的天数)。例如:给定时间为10,下次出现三个高峰同天的时间是12,则输出2(注意这里不是3)。
Input
输入四个整数:p, e, i和d。 p, e, i分别表示体力、情感和智力高峰出现的时间(时间从当年的第一天开始计算)。d 是给定的时间,可能小于p, e, 或 i。所有给定时间是非负的并且小于365, 所求的时间小于21252。
当p = e = i = d = -1时,输入数据结束。
Output
从给定时间起,下一次三个高峰同天的时间(距离给定时间的天数)。

采用以下格式:
Case 1: the next triple peak occurs in 1234 days.
注意:即使结果是1天,也使用复数形式“days”。
Sample Input
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
Sample Output
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.
Source
East Central North America 1999

问题分析和解题思路:

这是一道水题,一个模拟就可以搞定。这道题更好的方法是用数学法求解,也是题目的价值所在。运用的是中国剩余定理,更准确的说是运用了大衍求一法。先给出定理。有一个关于韩信的故事:

韩信是汉高祖刘邦手下的大将,他英勇善战,智谋超群,为汉朝的建立了卓绝的功劳。据说韩信的数学水平也非常高超,他在点兵的时候,为了保住军事机密,不让敌人知道自己部队的实力,先令士兵从1至3报数,然后记下最后一个士兵所报之数;再令士兵从1至5报数,也记下最后一个士兵所报之数;最后令士兵从1至7报数,又记下最后一个士兵所报之数;这样,他很快就算出了自己部队士兵的总人数,而敌人则始终无法弄清他的部队究竟有多少名士兵。

这个故事中所说的韩信点兵的计算方法,就是现在被称为“中国剩余定理”的一次同余式解法。它是中国古代数学家的一项重大创造,在世界数学史上具有重要的地位。最早提出并记叙这个数学问题的,是南北朝时期的数学著作《孙子算经》中的“物不知数”题目。这道“物不知数”的题目是这样的:
“今有一些物不知其数量。如果三个三个地去数它,则最后还剩二个;如果五个五个地去数它,则最后还剩三个;如果七个七个地去数它,则最后也剩二个。问:这些物一共有多少?”
用简练的数学语言来表述就是:求这样一个数,使它被3除余2,被5除余3,被7除余2。《孙子算经》给出了这道题目的解法和答案。这相当于求不定方程组N=3x+2,N=5y+3,N=7x+2的正整数解N。《孙子算经》所给答案是N=23。由于孙子问题数据比较简单,这个答数通过试算也可以得到。但是《孙子算经》并不是这样做的。“物不知数”题的术文指出解题的方法多三三数之,取数七十,与余数二相乘;五五数之,取数二十一,与余数三相乘;七七数之,取数十五,与余数二相乘。将诸乘积相加,然后减去一百零五的倍数。列成算式就是:
  N=70×3+21×8+15×2-2×105。
  这里105是模数3、5、7的最小公倍数,容易看出,《孙子算经》给出的是符合条件的最小正整数。对于一般余数的情形,《孙子算经》术文指出,只要把上述算法中的余数2、8、2分别换成新的余数就行了。
后人总结成了便于记忆的诗句:
“三人同行七十稀,五树梅花廿一枝,
七子团圆正半月,除百令五便得知。”
《孙子算经》没有说明这三个数的来历。实际上,它们具有如下特性:
  也就是说,这三个数可以从最小公倍数M=3×5×7=105中各约去模数3、5、7后,再分别乘以整数2、1、1而得到。假令k1=2,K2=1,K3=1,那么整数Ki(i=1,2,3)的选取使所得到的三数70、21、15被相应模数相除的时候余数都是1。由此出发,立即可以推出,在余数是R1、R2、R3的情况下的情况。
  应用上述推理,可以完全类似地把孙子算法推广到一般情形:设有一数N,分别被两两互素的几个数a1、a2、……an相除得余数R1、R2、……Rn,即
  N≡Ri(mod ai)(i=1、2、……n),
  只需求出一组数K,使满足
  1(mod ai)(i=1、2、……n),
  那么适合已给一次同余组的最小正数解是
(P是整数,M=a1×a2×……×an),N=70×R1+21×R2+15×R3-P×105(p是整数)。
说的简单点,剩余定理的这个例子相当于:
n%3=2,n%5=3,n%7=2且3,5,7互质
使5×7被3除余1,用35×2=70;
使3×7被5除余1,用21×1=21;
使3×5被7除余1,用15×1=15。
(70×2+21×3+15×2)%(3×5×7)=23
同样,这道题也应该是:
使33×28被23除余1,用33×28×6=5544;
使23×33被28除余1,用23×33×19=14421;
使23×28被33除余1,用23×28×2=1288。
(5544×p+14421×e+1288×i)%(23×28×33)=n+d
n=(5544×p+14421×e+1288×i-d)%(23×28×33)

至此,这题得解。

AC代码:

#include<stdio.h>

int main()

{

int a,b,c,d,day,n=0;//a、b、c、d分别为输入的四个数

while(scanf("%d%d%d%d",&a,&b,&c,&d)!=EOF)

{

n++;

if(a==-1&&b==-1&&c==-1&&d==-1) break;

day=(5544*a+14421*b+1288*c-d)%(23*28*33);

if(day<=0)

printf("Case %d: the next triple peak occurs in %d days./n",n,21252-d);

else  printf("Case %d: the next triple peak occurs in %d days./n",n,day);

}

return 0;

}


总结:

但凡数学题,一般来说如果可以用其他方法做的,数学方法的时间度以及代码量等方面都会优于其他方法,因此,对于数学题,要尽量用数学方法求解。平时要注重数学题的独立思考和独立解决,提高数学能力。同样的,一道题也要多方面思考,争取多角度多算法解决。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: