zoukankan      html  css  js  c++  java
  • POJ1006Biorhythms

    转载请注明出处:優YoU   http://user.qzone.qq.com/289065406/blog/1309411846

     

    大致题意:

    这题在POJ上有译文(原文右上角)

     

    解题思路:

    中国剩余定理,本题难点不在编程,而是分析题目并转化为数学公式

    要引入本题解法,先来看一个故事 “韩信点兵”:
          
    传说西汉大将韩信,由于比较年轻,开始他的部下对他不很佩服。有一次阅兵时,韩信要求士兵分三路纵队,结果末尾多2人,改成五路纵队,结果末尾多3人,再改成七路纵队,结果又余下2人,后来下级军官向他报告共有士兵2395人,韩信立即笑笑说不对(因2395除以3余数是1,不是2),由于已经知道士兵总人数在2300~2400之间,所以韩信根据23128233------,每相邻两数的间隔是105357的最小公倍数),便立即说出实际人数应是2333人(因2333=128+20χ105+105,它除以32,除以53,除以72)。这样使下级军官十分敬佩,这就是韩信点兵的故事。 

     

     韩信点兵问题简化:已知 n%3=2,  n%5=3,  n%7=2,  n 


      
    再看我们这道题,读入p,e,i,d 4个整数

    已知(n+d)%23=p;   (n+d)%28=e;   (n+d)%33=i , 

     

    两道题是一样的。但是韩信当时计算出结果的? 
     
    韩信用的就是中国剩余定理,《孙子算经》中早有计算方法,大家可以查阅相关资料。 
    “韩信点兵”问题计算如下: 

    因为n%3=2, n%5=3, n%7=2 357互质 (互质可以直接得到这三个数的最小公倍数)

    x= n%3=2 y= n%5=3 z= n%7=2
          
    使5×7×a3除余1,有35×2=70,即a=2 
           
    使3×7×b5除余1,用21×1=21,即b=1 
           
    使3×5×c7除余1,用15×1=15,即c=1 
    那么n =70×x+21×y+15×z%lcm(3,5,7) = 23 这是n的最小解

     而韩信已知士兵人数在2300~2400之间,所以只需要n+i×lcm(3,5,7)就得到了2333,此时i=22

    同样,这道题的解法就是: 

    已知(n+d)%23=p;   (n+d)%28=e;   (n+d)%33=i 
           
    使33×28×a23除余1,用33×28×8=5544 
           
    使23×33×b28除余1,用23×33×19=14421 
           
    使23×28×c33除余1,用23×28×2=1288 
          
    因此有(5544×p+14421×e+1288×i% lcm(23,28,33) =n+d 

    232833互质,即lcm(23,28,33)= 21252;
          
    所以有n=5544×p+14421×e+1288×i-d%21252

    本题所求的是最小整数解,避免n为负,因此最后结果为n= [n+21252]% 21252
    那么最终求解n的表达式就是:

    n=(5544*p+14421*e+1288*i-d+21252)%21252;

    当问题被转化为一条数学式子时,你会发现它无比简单。。。。直接输出结果了。

     

     

     1 //Memory Time 
    2 //256K 94MS
    3
    4 #include<iostream>
    5 using namespace std;
    6
    7 int main(void)
    8 {
    9 int p,e,i,d;
    10 int time=1;
    11 while(cin>>p>>e>>i>>d)
    12 {
    13 if(p==-1 && e==-1 && i==-1 && d==-1)
    14 break;
    15
    16 int lcm=21252; // lcm(23,28,33)
    17 int n=(5544*p+14421*e+1288*i-d+21252)%21252;
    18 if(n==0)
    19 n=21252;
    20 cout<<"Case "<<time++<<": the next triple peak occurs in "<<n<<" days."<<endl;
    21 }
    22 return 0;
    23 }
  • 相关阅读:
    图片上下左右居中
    点击滚动指定高度 屏幕滚动事件
    实例16 验证登录信息的合法性
    实例15 判断某一年是否为闰年
    实例14 实现两个变量的互换(不借助第3个变量)
    实例13 不用乘法运算符实现2*16
    实例12 用三元运算符判断奇数和偶数
    实例11 加密可以这样简单(位运算)
    实例10 自动类型转换与强制类型转换
    实例9 重定向输入流实现程序日志
  • 原文地址:https://www.cnblogs.com/lyy289065406/p/2122797.html
Copyright © 2011-2022 走看看