您的位置:首页 > 其它

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

2017-03-02 20:55 295 查看
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示例
3
2 1
3 2
5 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息