POJ 1006 中国余数定理

来源:互联网 发布:新浪网络经纪人 编辑:程序博客网 时间:2024/05/01 16:42

这里题考查的 并不是 编程题,严格来说, 是一道数学题。

主要考察中国余数定理。

这里举一个典型的例子,就是,n % 3 = 2, n % 5 = 3, n % 7 = 2; 问n是多少?

这道题枚举当然可以算出来,但是运用定理可以将复杂度降到O(1),它是怎么做到的呢?

首先,我们求出5*7的倍数,并且它除以3余1; 同理,求出3*7的倍数,并且它除以5余1;  同理,求出3*5的倍数,并且它除以7余1.

然后我们将求出的三个数,暂且称为a,b,c . 做一个简单的运算,也就是求和sum = 2*a + 3*b + 2*c

最后,求出3,5,7的最小公倍数lcm(3,5,7) .那么结果也就是result = sum % lcm


那么回到这个题目,我们可以列出这样的等式:

(n+d)%23 = p

(n+d)%28 = e

(n+d)%33 = i

题目也就是要我们求n, 这里我们可以求得 sum = p*5544 + e*14421 + i*1288

 这里的5544,14421,1288怎么得来,当然可以借助for循环,当满足条件时将倍数输出,即可,这里的倍数分别是6,19,2

所以,最后的结果是 result = (sum - d + 21252)%lcm(23,28,33)

这里为什么要将 -d 放在括号里面,因为防止这样的情况,结果应该为21252,放在外面会变成0. 例子:19 0 1 364

这里注意的是,括号里面加了一个21252,这样是为了防止 出现负数

#include<iostream>using namespace std;int main(){    int p,e,i,d;    int count=1;    int lcm = 23*28*33;    int days;    while(cin>>p>>e>>i>>d){        if(p==-1&&e==-1&&i==-1&&d==-1)            break;        days = (5544*p+14421*e+1288*i-d)%lcm;        days = (days+21252)%21252;    //防止产生负数        if(days == 0)            days = 21252;        cout<<"Case "<<count<<": the next triple peak occurs in "<<days<<" days."<<endl;        count++;    }    return 0;}


0 0
原创粉丝点击