您的位置:首页 > 其它

中国剩余定理

2017-09-14 13:37 190 查看

韩信点兵的故事大家一定都听说过,韩信让士兵分别3个3个报数多2人,5个5个报数多4人,7个7个报数多6人,通过每次报数的余数计算出军队的人数。


其实,韩信所做的,就是解了三个同余方程:

x≡2 (mod 3)

x≡4 (mod 5)

x≡6 (mod 7)

怎么解呢?古人想了一个聪明的办法:

找一个数x1,使得它是5和7的倍数,而除3余2,

找一个数x1,使得它是7和3的倍数,而除5余4,

找一个数x1,使得它是5和3的倍数,而除7余6,

然后三个数加起来,就一定满足这个条件,而且解周期为3*5*7


中国剩余定理

我们把这个算法拓展,对于任意的方程组x≡bi (mod mi) 即: x≡b1 (mod m1)
x≡b2 (mod m2)
x≡b3 (mod m3)
...... x≡bn (mod mn)

其中m都是互质的
那么我们对于每一个方程,算出一个xi,使得xi满足:xi≡1 (mod mi) 且xi≡0 (mod mj)【j!=i】 也就是说xi是其他m的倍数,而模mi余1 y*(N/mi)≡1 (mod mi)  【N=m1*m2*m3*......mn】用扩展欧几里得算法就可以解出了 那么最终的x=(x1*b1+x2*b2+x3*b3+......xn*bn) mod N   【N=m1*m2*m3*......mn】
【我懒就先不打代码了= =】

水题:POJ1006
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long int
using namespace std;
const int maxn=100005,INF=2000000000,P=1000000007;

void exgcd(int a,int b,int& d,int& x,int& y){
if(!b) {d=a;x=1;y=0;}
else exgcd(b,a%b,d,y,x),y-=(a/b)*x;
}

int main(){
int N=21252,A[4],T[4]={0,23,28,33},t,ans=0,cnt=0;
while(cin>>A[1]>>A[2]>>A[3]>>t){
if(t==-1) break;
ans=0;
cnt++;
for(int i=1;i<=3;i++){
int x,y,a=T[i],b=N/T[i],d;
exgcd(a,b,d,x,y);
ans=(ans+y*b*A[i])%N;
}
ans=((ans-t)%N+N)%N;
if(!ans) ans+=N;
printf("Case %d: the next triple peak occurs in %d days.\n",cnt,ans);
}
return 0;
}



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: