您的位置:首页 > 其它

poj 2891(中国剩余定理 ------迭代法来求解)

2011-09-04 11:25 507 查看
这个题不能直接应用中国剩余定理,因为m的值可能不互素。。。。所以用两两求解的方法来求解(应该是叫迭代吧。。。自己是这么跟别人说的。。。)看下面的例子。。

x = 1 (mod 5)

x = 2 (mod 6)

x = 3 (mod 7)

首先我们把第一个方程写成 x = 5*t+1 ,然后带入第二个方程,得5*t + 1 = 2(mod 6) ==> t = 5(mod 6) ;再写成 t = 6*u+5

则 x = 5*(6*u+5)+1 = 30 *u +26; 再次带入第三个方程,30 *u +26=3(mod 7) 可以得出 u=6(mod 7);

则 u = 7*v+6 ; x = 30*(7*v + 6)+26=210*v+206;

所以 x = 206(mod 207);

就按照这样不断更新 a*x=b(mod n) 中的a 和 n ,逐次带入来求解。。。。。

#include <iostream>
using namespace std;
#define LL long long
LL ex_gcd(LL a, LL b, LL &x, LL &y) {
if (b == 0) {
x = 1, y = 0;
return a;
}
LL d = ex_gcd(b, a % b, x, y);
LL t = x;
x = y;
y = t - a / b*y;
return d;
}
LL mod(LL a,LL b,LL n,LL &d){ // a*x=b(mod n) ,d 是返回a, n的最大公约数
LL e,x,y;
d=ex_gcd(a,n,x,y);
if(b%d!=0) return -1;
e=(x*(b/d))%n;
while(e<0) e+=n/d; // a,n 可能不互素 所以加n/d 可以得到最小正整数解
return e;
}
int main(int argc, char** argv) {
bool flag;
LL m,a1,m1,a2,m2,x,d;
while(scanf("%lld",&m)!=-1){
scanf("%lld%lld",&m1,&a1);
flag=0;
for(int i=1;i<m;i++){
scanf("%lld%lld",&m2,&a2);
if(flag) continue;
x=mod(m1,a2-a1,m2,d);
if(x==-1){
flag=1; continue;
}
a1+=m1*x;
m1=m1*m2/d;
a1=(a1%m1+m1)%m1;
}
if(flag)
printf("-1\n");
else
printf("%lld\n",a1);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: