POJ 1006 中国余数定理

116 篇文章 2 订阅
27 篇文章 0 订阅

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

主要考察中国余数定理。

这里举一个典型的例子,就是,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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值