51nod:1079 中国剩余定理(数学)

来源:互联网 发布:kindle微信推送 知乎 编辑:程序博客网 时间:2024/05/23 16:54
1079 中国剩余定理
基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题
 收藏
 关注
一个正整数K,给出K Mod 一些质数的结果,求符合条件的最小的K。例如,K % 2 = 1, K % 3 = 2, K % 5 = 3。符合条件的最小的K = 23。
Input
第1行:1个数N表示后面输入的质数及模的数量。(2 <= N <= 10)第2 - N + 1行,每行2个数P和M,中间用空格分隔,P是质数,M是K % P的结果。(2 <= P <= 100, 0 <= K < P)
Output
输出符合条件的最小的K。数据中所有K均小于10^9。
Input示例
32 13 25 3
Output示例
23


中国剩余定理:
在这之前,先记住这俩定理,在看下面文字时,有不懂的就想想这俩定理:

定理1:几个数相加,如果只有一个加数,不能被数a整除,而其他加数均能被数a整除,那么它们的和,就不能被整数a整除。


定理2:二数不能整除,若除数扩大(或缩小)了几倍,而除数不变,则其余数也同时扩大(或缩小)相同的倍数(余数必小于除数)。


我国的数学文化历史悠久。我们的祖先从上古末
开化时代开始,经过许多世代,通过大量的生产实践
和生活实际的研究,创造了许多宝贵的数量文献。
《孙子算经》
(大约公元四世纪、晋朝时期成书)中的“物不知其数”问题的解法是中国数学领先于世界的一个典型例子。它便是最早的
“中国剩余定理”。1.《孙子算经》,最早的“中国剩余定理”
“物不知其数”问题:今有物不知其数,三三数之剩二,五五数之剩三,七七数之剩二,问物几何?答曰:二十三。书中问题的奇妙解法是:三三数之剩二,置一百四十;五五数之剩三,置六十三;七七数之剩二,置三十。并之得二百三十三,以二百一十减之即得二十三。

该算法用口诀表达是:“三人同行七十稀,五树梅花廿一枝,七子团圆正半月,除百零五便得知。”意思是:每3个一数最后剩1个就取5和7的公倍数70(先让他剩1,再用定理2),那么“三三数之剩二个”,就取二倍个70得140(定理2);每5个一数最后剩1个就取3和7的公倍数21,那么“五五数之剩三个”
,就取
三倍个21得63;每7个一数最后剩1个就取3和5的公倍数15,那么“七七数之剩二个”,就取二倍个15得30。最后把140,63,30三数相加的和再减去3、5、7的公倍数105×2,即得符合条件的最小数为23。于是就有:70×2+21×3+15×2-105×2=23。



(注意看这里,ai就是每个余数了,ti先不管,Mi是除了当下的除数之外的所有除数之积。ai不用求,Mi好求,这里ti怎么求呢?ti的意义就是设ax+by=1之中的x,而a是上面的Mi,b是当前除数,那么by就相当于b个b个数的话,数y组的意思,a就是除了当下的除数之外的所有除数之积,由于ai都是质数,所以a是其余除数的最小公倍数,那么求出x就是上面绿字过程。怎么求x也就是ti呢?用exgcd解就行

代码如下:
#include <cstdio>typedef long long LL;LL n,chu[11],yu[11];LL x,y;void exgcd(LL a,LL b)//exgcd求不定方程ax+by=gcd(a,b)=1(a,b互质) {if(b==0){x=1;y=0;return ;}exgcd(b,a%b);LL tmp=x;x=y;y=tmp-(a/b)*y;}LL chinese(){LL allji=1;for(int i=0;i<n;i++)//先求出所有的除数之积,以便于球下面的mi {allji=allji*chu[i];}LL ans=0;for(int i=0;i<n;i++){LL mi=allji/chu[i];exgcd(mi,chu[i]);//求x ,也就是ti ans=(ans+(yu[i]*x*mi)%allji)%allji;}if(ans<0)//防止结果是负数 {ans=ans+allji;}return ans;}int main(){scanf("%lld",&n);for(int i=0;i<n;i++){scanf("%lld%lld",&chu[i],&yu[i]); }  printf("%lld\n",chinese()); return 0;} 



还有一种写法,也值得学习下(适合小数据):
例7:一个班学生分组做游戏,如果每组三人就多两人,每组五人就多三人,每组七人就多四人,问这个班有多少学生? 
题目可以看成,除3余2,除5余3,除7余4。没有同余的情况,用的方法是“逐步约束法”,就是从“除7余4的数”中找出符合“除5余3的数”,就是再7上一直加7,直到所得的数除5余3。得出数为18,下面只要在18上一直加7和5得最小公倍数35,直到满足“除3余2” 
4+7=11 
11+7=18 
18+35=53
摘自:http://blog.csdn.net/qq_32734731/article/details/51890220
#include <cstdio>typedef long long LL;LL n,chu[11],yu[11];int main(){scanf("%lld",&n);for(int i=0;i<n;i++){scanf("%lld%lld",&chu[i],&yu[i]);}LL ans=yu[0];LL lcm=1;for(int i=0;i<n-1;i++){lcm=lcm*chu[i];while(ans%chu[i+1]!=yu[i+1]){ans=ans+lcm;}}printf("%lld\n",ans);return 0;}


0 0
原创粉丝点击