中国剩余定理

poj 1006是说一个数通过n个除数得到不同的余数,求总数

http://poj.org/problem?id=1006&lang=zh-CN&change=true

先看两个小学生题目

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

2.《孙子算经》中的题目:有物不知其数,三个一数余二,五个一数余三,七个一数又余二,问该物总数几何?  《孙子算经》中的解法:三三数之,取数七十,与余数二相乘;五五数之,取数二十一,与余数三相乘;七七数之,取数十五,与余数二相乘。将诸乘积相加,然后减去一百零五的倍数。

(解为:(70*2+21*3+15*2)%3*5*7=23)


poj1006其实看的是中国剩余定理(孙子定理)的使用,而非for的使用。。。。


理论基础:

令某数为M,令素数为A,B,C,D,…,Z,已知M/A余a,M/B余b,M/C余c,M/D余d,…,M/Z余z。求M=?  

因为A,B,C,D,…,Z为不同的素数,故,B*C*D*…*Z不可能被A整除,有等差数列(B*C*D*…*Z)+(B*C*D*…*Z)N中取A个连续项,这A个连续项分别除以A的余数必然存在0,1,2,3,…,A-1,

解法

⒈分别找出能被两个数整除,而满足被第三个整除余一的最小的数。(这样就避免了35,70,105...一直碰撞)

⒉将三个未知数乘对应数字的余数再加起来,减去这三个数的最小公倍数的整数倍即得结果。


poj 1006 程序:

//Memory Time
//256K   94MS

#include<iostream>
using namespace std;
int main(void)
{
      int p,e,i,d;
      int time=1;
      while(cin>>p>>e>>i>>d)
      {
           if(p==-1 && e==-1 && i==-1 && d==-1)
                 break;

           int lcm=21252;  // lcm(23,28,33)
           int n=(5544*p+14421*e+1288*i-d+21252)%21252;
           if(n==0)
                 n=21252;
           cout<<"Case "<<time++<<": the next triple peak occurs in "<<n<<" days."<<endl;
      }
      return 0;
}

上面把iostream换成c系的stdio.h,程序内存小了,时间慢了。算是额外收货
参考:

http://user.qzone.qq.com/289065406/blog/1309411846#!app=2&via=QZ.HashRefresh&pos=1309411846

http://baike.baidu.com/view/157384.htm?subLemmaId=157384&fromenter=%D6%D0%B9%FA%CA%A3%D3%E0%B6%A8%C0%ED



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值