警告:这不是一道水题
说真的,连着刷了5道水题,突然间碰到这道题还真的有点不适应。。。。
题目大意:
有三个循环周期:23,28,33。
先给你这三个周期距离下一次峰值的天数:p,e,i
再给你一个起始日期:d
求:从d天后再过多少天三个周期能同时达到峰值?
有木有乍一看很简单,细想想却又无从下手的赶脚?
抛开这道题,我们先研究一个很古老却又很深奥的问题:中国剩余定理
《孙子算经》中有“物不知数”问题:“今有物不知其数,三三数之余二 ,五五数之余三 ,七七数之余二,问物几何?”
翻译一下就是n % 3 = 2, n % 5 = 3, n % 7 = 2; 问n是多少?
再回过头来看题,假设n天后三个周期能同时达到峰值。是不是能够得到:
(n+d) % 23 = p;
(n+d) % 28 = e;
(n+d) % 33 = i;
看看看,是不是一毛一样!
好了,现在该研究研究怎么求这个n了。。。
现在的已知条件只有n % 3 = 2, n % 5 = 3, n % 7 = 2。
我们拆开来看这三个条件,假设有3个数n1,n2,n3
使得n1能够整除5跟7,但是n1%3=2
使得n2能够整除3跟7,但是n2%5=3
使得n3能够整除3跟5,但是n3%7=2
是不是(n1+n2+n3) % 3 = 2, (n1+n2+n3) % 5 = 3, (n1+n2+n3) % 7 = 2就成立了!
好了,接下来我们在看看n1,n2,n3该怎么求
假设a能够整除5跟7,a%3=1。那么a*2 % 3=2成立
假设b能够整除3跟7,b%7=1。那么b*3 % 5=3成立
假设c能够整除3跟5,c%7=1。那么c*2 % 7=2成立
所以:a=70,b=21,c=15
所以:n1=140,n2=63,n3=30
所以:n=233!
但是233明显不是最优解;
n=233 % 105(3,5,7的最小公倍数)=23
bingo!
再回过头来看poj1006,求这里面的a,b,c
a=5544
b=14421
c=1288
day = (5544 * p + 14421 * e + 1288 * i - d + 21252) % 21252;
代码如下:
#include <iostream>
using namespace std;
int main(){
int p, e, i, d, day, num = 1;
while (cin >> p >> e >> i >> d && p != -1 && e != -1 && i != -1 && d != -1){
day = (5544 * p + 14421 * e + 1288 * i - d + 21252) % 21252;
cout << "Case "<< num << ": the next triple peak occurs in " << ((day == 0) ? 21252 : day) << " days." << endl;
num++;
}
return 0;
}
本文深入探讨了中国剩余定理的应用,通过一道经典题目,将古老的数学问题与现代编程结合,展示了如何利用该定理解决周期同步问题,并提供了详细的算法解析及代码实现。
2955

被折叠的 条评论
为什么被折叠?



