[POJ]1006:Biorhythms

百练.1006
这道题可以转化为剩余定理问题,类似的著名例子有“韩信点兵”。

思路:

1.从23和28的公倍数中找出被33除余1的数x,从23和33的公倍数中找出被28除余1的数y,从28和33的公倍数中找被23除余1的数z。

通过(23·28·a)%33 = 1得到a = 2,进而知道x = 1288
同理,y = 14421,z = 4620

2.求和sum = x·p + y·e + z·i
3.用sum%lcm(23,28,33)=n+d(n即为问题的解)

分析:

理论推导需要两个定理

  1. 如果a%b=c,则有(a+kb)%b=c(k为非负整数)
  2. 如果a%b=c,那么(ka)%b=kc(k为正整数)

中国剩余定理介绍
在《孙子算经》中有这样一个问题:“今有物不知其数,三三数之剩二(除以 3 余 2),
五五数之剩三(除以 5 余 3),七七数之剩二(除以 7 余 2),问物几何?” 这个问题称为 “孙
子问题”,该问题的一般解法国际上称为 “中国剩余定理”。

这种题的最终结果n需满足三个条件:n mod 3 = 2, n mod 5 = 3, n mod 7 = 2, 那么我们就要开始试图寻找这个最小的n。
既然这个数n需要满足上面三个条件,我们就可以利用上面的定理1,将这个数n拆分成三个数n1,n2,n3,那么怎么找到这三个数呢(或者这三个数有什么性质呢)?
假设:n2和n3都是3的倍数,那么根据定理1,(n1 + n2 + n3)%3 = (n1 + 3k)%3 = n%3 = 2,这样最终结果n满足第一个条件。
同理,如果n1和n3是5的倍数,n1和n2是7的倍数,那么最终结果n = n1 + n2 + n3就会满足上面的三个条件!

寻找n1,n2,n3时还有一个技巧,以n1为例,先找n1 mod 3 = 1,然后再将求出的n1乘上余数2,利用上面的定理2可知,2n1符合条件。
最后将这些数相加,对lcm(3,5,7)取模,得出最小答案n。

代码

#include<stdio.h>
int main(int argc, char const *argv[])
{
    int p,e,i,d;
    int cnt = 1;
    while(scanf("%d%d%d%d",&p,&e,&i,&d)){
        if(p == -1 && p == e && p == i && p == d)
            break;
        int n = (28*33*6*p + 23*33*19*e + 23*28*2*i - d + 21252)%21252;//avoid n < 0,so n = (n + 21252)%21252
        if(n == 0)//lcm(23,28,33)=21252
            n = 21252;
        printf("Case %d: the next triple peak occurs in %d days.\n", cnt++,n);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/zhaijiayu/p/9630807.html