poj1006Biorhythms(同余定理)
转自:http://blog.csdn.net/dongfengkuayue/article/details/6461298
- 本文转自head for better博客,版权归其所有,代码系本人自己编写
问题描述
- 人自出生起就有体力,情感和智力三个生理周期,分别为23,28和33天。一个周期内有一天为峰值,在这一天,
- 人在对应的方面(体力,情感或智力)表现最好。通常这三个周期的峰值不会是同一天。
- 现在给出三个日期,分别对应于体力,情感,智力出现峰值的日期。然后再给出一个起始日期,
- 要求从这一天开始,算出最少再过多少天后三个峰值同时出现。
问题分析
- 首先我们要知道,任意两个峰值之间一定相距整数倍的周期。假设一年的第N天达到峰值,则下次达到峰值的时
- 间为N+Tk(T是周期,k是任意正整数)。所以,三个峰值同时出现的那一天(S)应满足
- S = N1 + T1*k1 = N2 + T2*k2 = N3 + T3*k3
- N1,N2,N3分别为为体力,情感,智力出现峰值的日期, T1,T2,T3分别为体力,情感,智力周期。
- 我们需要求出k1,k2,k3三个非负整数使上面的等式成立。
- 想直接求出k1,k2,k3貌似很难,但是我们的目的是求出S, 可以考虑从结果逆推。
- 根据上面的等式,S满足三个要求:除以T1余数为N1,除以T2余数为N2,除以T3余数为N3。
- 这样我们就把问题转化为求一个最小数,该数除以T1余N1,除以T2余N2,除以T3余N3。
- 这就是著名的中国剩余定理,我们的老祖宗在几千年前已经对这个问题想出了一个精妙的解法。
- 依据此解法的算法,时间复杂度可达到O(1)。下面就介绍一下中国剩余定理。
中国剩余定理介绍
- 在《孙子算经》中有这样一个问题:“今有物不知其数,三三数之剩二(除以3余2),五五数之剩三(除以5余3),
- 七七数之剩二(除以7余2),问物几何?”这个问题称为“孙子问题”,该问题的一般解法国际上称为“中国剩余定理”。
- 具体解法分三步:
- 找出三个数:从3和5的公倍数中找出被7除余1的最小数15,从3和7的公倍数中找出被5除余1 的最小数21,最后从5和7的公倍数中找出除3余1的最小数70。
2. 用15乘以2(2为最终结果除以7的余数),用21乘以3(3为最终结果除以5的余数),同理,用70乘以2(2为最终结果除以3的余数),然后把三个乘积相加(15*2+21*3+70*2)得到和233。
3.用233除以3,5,7三个数的最小公倍数105,得到余数23,即233%105=23。这个余数23就是符合条件的最小数。
就这么简单。我们在感叹神奇的同时不禁想知道古人是如何想到这个方法的,有什么基本的数学依据吗?
中国剩余定理分析
我们将“孙子问题”拆分成几个简单的小问题,从零开始,试图揣测古人是如何推导出这个解法的。
首先,我们假设n1是满足除以3余2的一个数,比如2,5,8等等,也就是满足3*k+2(k>=0)的一个任意数。同样,我们假设n2是满足除以5余3的一个数,n3是满足除以7余2的一个数。
有了前面的假设,我们先从n1这个角度出发,已知n1满足除以3余2,能不能使得 n1+n2 的和仍然满足除以3余2?进而使得n1+n2+n3的和仍然满足除以3余2?
这就牵涉到一个最基本数学定理,如果有a%b=c,则有(a+kb)%b=c(k为非零整数),换句话说,如果一个除法运算的余数为c,那么被除数与k倍的除数相加(或相减)的和(差)再与除数相除,余数不变。这个是很好证明的。
以此定理为依据,如果n2是3的倍数,n1+n2就依然满足除以3余2。同理,如果n3也是3的倍数,那么n1+n2+n3的和就满足除以3余2。这是从n1的角度考虑的,再从n2,n3的角度出发,我们可推导出以下三点:
- 为使n1+n2+n3的和满足除以3余2,n2和n3必须是3的倍数。
- 为使n1+n2+n3的和满足除以5余3,n1和n3必须是5的倍数。
- 为使n1+n2+n3的和满足除以7余2,n1和n2必须是7的倍数。
因此,为使n1+n2+n3的和作为“孙子问题”的一个最终解,需满足:
- n1除以3余2,且是5和7的公倍数。
- n2除以5余3,且是3和7的公倍数。
- n3除以7余2,且是3和5的公倍数。
所以,孙子问题解法的本质是从5和7的公倍数中找一个除以3余2的数n1,从3和7的公倍数中找一个
除以5余3的数n2,从3和5的公倍数中找一个除以7余2的数n3,再将三个数相加得到解。
在求n1,n2,n3时又用了一个小技巧,以n1为例,并非从5和7的公倍数中直接找一个除以3余2的数,
而是先找一个除以3余1的数,再乘以2。
这里又有一个数学公式,如果a%b=c,那么(a*k)%b=a%b+a%b+…+a%b=c+c+…+c=kc(k>0),
也就是说,如果一个除法的余数为c,那么被除数的k倍与除数相除的余数为kc。展开式中已证明。
最后,我们还要清楚一点,n1+n2+n3只是问题的一个解,并不是最小的解。如何得到最小解?
我们只需要从中最大限度的减掉掉3,5,7的公倍数105即可。
道理就是前面讲过的定理“如果a%b=c,则有(a-kb)%b=c”。所以(n1+n2+n3)%105就是最终的最小解。
总结
经过分析发现,中国剩余定理的孙子解法并没有什么高深的技巧,就是以下两个基本数学定理的灵活运用:
- 如果 a%b=c , 则有 (a+kb)%b=c (k为非零整数)。
- 如果 a%b=c,那么 (a*k)%b=kc (k为大于零的整数)。
- POJ1006其实不能算是一道编程难题,只是里面用到了剩余定理。
首先说一下数学上的计算。具体的资料可以在网上搜索一下“剩余定理”或者是“韩信点兵”。
- 因为23、28、33这3个数互质,
- 那么由剩余定理有:
R1为28*33*a%23==1的最小的正整数(a为正整数),即a=6,R1=5544
R2为23*33*b%28==1的最小的正整数(b为正整数),即b=19,R2=14421
R3为23*28*c%33==1的最小的正整数(c为正整数),即c=2,R3=1288
- #include <iostream>
- #include <cstring>
- #include <cstdio>
- #include <algorithm>
- using namespace std;
- int main()
- {
- int p, e, i, d;
- int test = ;
- while (scanf("%d%d%d%d", &p, &e, &i, &d) != EOF)
- {
- if (p == - && e == - && i == - && d == -)
- break;
- int sum = ( * p + e * + * i) % ;
- while (sum <= d)
- sum += ;
- printf("Case %d: the next triple peak occurs in %d days.\n", test++, sum - d);
- }
- return ;
- }
poj1006Biorhythms(同余定理)的更多相关文章
- Light oj 1214-Large Division (同余定理)
题目链接:http://lightoj.com/volume_showproblem.php?problem=1214 题意很好懂,同余定理的运用,要是A数被B数整除,那么A%B等于0.而A很大,那我 ...
- 如何运用同余定理求余数【hdoj 1212 Big Number【大数求余数】】
Big Number Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total ...
- hdu 4704 同余定理+普通快速幂
此题往后推几步就可找到规律,从1开始,答案分别是1,2,4,8,16.... 这样就可以知道,题目的目的是求2^n%Mod的结果.....此时想,应该会想到快速幂...然后接着会发现,由于n的值过大, ...
- OJ随笔——【1088-N!】——同余定理
题目如下: Description 请求N!(N<=10000),输出结果对10007取余输入每行一个整数n,遇到-1结束.输出每行一个整数,为对应n的运算结果. Sample Input ...
- [ACM] POJ 2635 The Embarrassed Cryptographer (同余定理,素数打表)
The Embarrassed Cryptographer Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 11978 A ...
- 算法训练 K好数 数位DP+同余定理
思路:d(i,j)表示以i开头,长度为j的K好数的个数,转移方程就是 for(int u = 0; u < k; ++u) { int x = abs(i - u); if(x == 1) co ...
- poj1061-青蛙的约会-(贝祖定理+扩展欧几里得定理+同余定理)
青蛙的约会 Time Limit: 1000MS Memory Limit: 10000K Total Submissions:132162 Accepted: 29199 Descripti ...
- hdu1576-A/B-(同余定理+乘法逆元+费马小定理+快速幂)
A/B Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submiss ...
- HDU1212 Big Number 【同余定理】
Big Number Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total ...
随机推荐
- 压缩Sqlite数据文件大小,解决数据删除后占用空间不变的问题
最近有一网站使用Sqlite数据库作为数据临时性的缓存,对多片区进行划分 Sqlite数据库文件,每天大概新增近1万的数据量,起初效率有明显的提高,但历经一个多月后数据库文件从几K也上升到了近160M ...
- ORACLE查看补丁出现“OPatch failed with error code 1”
案例场景: 在Oracle Linux Server release 5.7上安装完ORACLE 10g后,顺便将PSR(Patch Set Release)p681018 ...
- RMAN还原遭遇ORA-32006&ORA-27102错误
案例环境: 服务器A: 操作系统 : Red Hat Enterprise Linux ES release 4 (Nahant Update 6) 数据库版本: Oracle Database ...
- leveldb源码分析--SSTable之Compaction
对于compaction是leveldb中体量最大的一部分,也应该是最为复杂的部分,为了便于理解我们首先从一些基本的概念开始.下面是一些从doc/impl.html中翻译和整理的内容: Level 0 ...
- Java实现不同的WebService 调用方式
请求过程分析: 1.使用get方式获取wsdl文件,称为握手 2.使用post发出请求 3.服务器响应成功 几种监听工具: http watch Web Service explorer eclips ...
- 遇到shell重定向的一个奇怪问题:'消失'的标准输入!
需求: 把找到的文件逐行输出,然后用rm在许可的情况下删除 前置准备: $ls rm.sh test1 test2 test3 test4 test5 test6 $cat rm.sh #! / ...
- linux yum 工具
vim /etc/yum.repos.d/CentOS-Base.repo 编辑yum 源网址 yum list |grep vim查看vim 情况 yum remove 卸载rpm包 # yum u ...
- Centos下yum安装PHP
添加 yum 源 Centos 6.x 的源 # rpm -Uvh http://download.fedoraproject.org/pub/epel/6/x86_64/epel-release-6 ...
- ffmbc——广播电视以及专业用途量身定制的FFmpeg
做项目遇到针对于mpegts多节目流转码的问题,看遍了ffmpeg的参数都得不到解决办法,最后在雷神的博客中看到了ffmbc: 结果,还是没解决问题,但是看起来改改ffmbc的代码还是相对简单一些,抽 ...
- 阅读ArrayBlockingQueue源码了解如何利用锁实现BlockingQueue
BlockingQueue是多线程里面一个非常重要的数据结构.在面试的时候,也常会被问到怎么实现BlockingQueue.本篇根据Java7里ArrayBlockingQueue的源码,简单介绍一下 ...