Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 111285 | Accepted: 34638 |
Description
Input
Output
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
题目大意:
人自出生起就有体力,情感和智力三个生理周期,分别为23,28和33天。一个周期内有一天为峰值,在这一天,人在对应的方面(体力,情感或智力)表现最好。通常这三个周期的峰值不会是同一天。现在给出三个日期,分别对应于体力,情感,智力出现峰值的日期。然后再给出一个起始日期,要求从这一天开始,算出最少再过多少天后三个峰值同时出现。
解题思路:
首先化简一下问题:欲求从某天开始,算出再过多少天后三个峰值同时出现,设要求的这个值为ans
如果我们能找到一天,三个峰值同时出现,我们记这天为 x ,再记 体力,情感,智力出现峰值的日期 分别为 a,b,c ,起始日期为 d.
那么必然:满足条件 x=a+23*t1=b+28*t2=c+33*t2.
再看一下 ans 与 x 的关系:ans = ( x - d ) % (23*28*33) ,所以求出 x 就可以了。
求X要用到 中国剩余定理
【转】自:点击打开链接
在《孙子算经》中有这样一个问题:“今有物不知其数,三三数之剩二(除以3余2),五五数之剩三(除以5余3),七七数之剩二(除以7余2),问物几何?”这个问题称为“孙子问题”,该问题的一般解法国际上称为“中国剩余定理”。具体解法分三步:
我们将“孙子问题”拆分成几个简单的小问题,从零开始,试图揣测古人是如何推导出这个解法的。
首先,我们假设n1是满足除以3余2的一个数,比如2,5,8等等,也就是满足3*k+2(k>=0)的一个任意数。同样,我们假设n2是满足除以5余3的一个数,n3是满足除以7余2的一个数。
有了前面的假设,我们先从n1这个角度出发,已知n1满足除以3余2,能不能使得 n1+n2 的和仍然满足除以3余2?进而使得n1+n2+n3的和仍然满足除以3余2?
这就牵涉到一个最基本数学定理,如果有a%b=c,则有(a+kb)%b=c(k为非零整数),换句话说,如果一个除法运算的余数为c,那么被除数与k倍的除数相加(或相减)的和(差)再与除数相除,余数不变。这个是很好证明的。
以此定理为依据,如果n2是3的倍数,n1+n2就依然满足除以3余2。同理,如果n3也是3的倍数,那么n1+n2+n3的和就满足除以3余2。这是从n1的角度考虑的,再从n2,n3的角度出发,我们可推导出以下三点:
因此,为使n1+n2+n3的和作为“孙子问题”的一个最终解,需满足:
所以,孙子问题解法的本质是从5和7的公倍数中找一个除以3余2的数n1,从3和7的公倍数中找一个除以5余3的数n2,从3和5的公倍数中找一个除以7余2的数n3,再将三个数相加得到解。在求n1,n2,n3时又用了一个小技巧,以n1为例,并非从5和7的公倍数中直接找一个除以3余2的数,而是先找一个除以3余1的数,再乘以2。
这里又有一个数学公式,如果a%b=c,那么(a*k)%b=a%b+a%b+…+a%b=c+c+…+c=kc(k>0),也就是说,如果一个除法的余数为c,那么被除数的k倍与除数相除的余数为kc。展开式中已证明。
最后,我们还要清楚一点,n1+n2+n3只是问题的一个解,并不是最小的解。如何得到最小解?我们只需要从中最大限度的减掉掉3,5,7的公倍数105即可。道理就是前面讲过的定理“如果a%b=c,则有(a-kb)%b=c”。所以(n1+n2+n3)%105就是最终的最小解。
解题代码:
#include <iostream> #include <cstdio> using namespace std; int a,b,c,d; int n1,n2,n3; void get(){//get n1,n2,n3 for(int i=1;;i++){ if(28*33*i%23==1){ n1=28*33*i; break; } } for(int i=1;;i++){ if(23*33*i%28==1){ n2=23*33*i; break; } }for(int i=1;;i++){ if(23*28*i%33==1){ n3=23*28*i; break; } } } int main(){ get(); int casen=0; while(scanf("%d%d%d%d",&a,&b,&c,&d)!=EOF){ if( a==-1 && b==-1 && c==-1 && d==-1) break; int ans=(n1*a+n2*b+n3*c-d)%(23*28*33); ans=ans<=0?ans+23*28*33:ans; printf("Case %d: the next triple peak occurs in %d days.\n",++casen,ans); } return 0; }
POJ 1006 Biorhythms (数论-中国剩余定理),布布扣,bubuko.com
POJ 1006 Biorhythms (数论-中国剩余定理)
原文:http://blog.csdn.net/a1061747415/article/details/31371413