您的位置:首页 > 理论基础 > 计算机网络

http://acm.pku.edu.cn/JudgeOnline/problem?id=2891 欧几里德线性同余方程

2010-08-11 12:50 447 查看
]/*
对于同余方程组:
x=a1 (mod m1)
x=a2 (mod m2)
方程组有一个小于m(m1,m2的最小公倍数)的非负整数解的充要条件是(a1-a2)%gcd(m1,m2)=0,同样利用扩展欧几里得算法。两式联立:a1+m1*y=a2+m2*z
则:a1-a2=m2*z-m1*y这样就可以解出z和y,则:x=a2+m2*z
而对于一般情形:(设m1,m2,...mk两两互素)时有:
a=b[1] (mod w[1])
a=b[2] (mod w[2])
.....
a=b
(mod w
)
其中w,b已知,w[1],w[2]...w
是两两互素的正整数,求a
令W=w[1]*w[2]*...w
,用W[i]=W/w[i],因为gcd(W[i],w[i])=1,故有;两整数p[i],q[i]满足W[i]*p[i]+w[i]*q[i]=1;如果记e[i]=W[i]*p[i],那么当j!=i时有:e[i]=0 (mod w[j]),当j=i时有:e[i]=1 (mod w[j]);
所以很明显:e[1]*b[1]+e2*b[2]+......e[k]*b[k]就是方程的一个解,加减W倍后就可以得到最小非负整数解了
而对于w[1],w[2].....w
不互素的情形,就只能两个两个来求了
x=a[1] (mod m[1])
x=a[2] (mod m[2])
解完后,a=x,m=m1和m2的最小公倍数
将题目意思转化为公式:a1*x-a2*y=r2-r1,用欧几里得扩展算法求解
题意是说,给一组a[i],r[i],求一个最小的m,满足 for_each(i=0: n) m % a[i] = r[i]
即 a[i]*x+r[i]=m,不存在输出-1。
我们首先得到 a1 * x + r1 = m 和 a2 * y + r2 = m,联立得到
a1 * x - a2 * y = r2 - r1,利用ex_gcd解之,先解得a1*X-a2*Y=GCD(a1,a2)时的X Y值和a1,a2的gcd,x y存在整数解的条件是 gcd | r2-r1.是否输出-1就是从这判断。有解即为
x=(r2-r1)/gcd*X
tmp=a2/gcd,  x=( ( r2 - r1 ) / gcd * X % tmp + tmp ) % tmp;
接着输入下一组a3,r3,问题变为求满足LCM(a1,a2)%m1=m和
a3%m1=r3的新的m值:m1
LCM(a1,a2) * x + a3 * y = r3 - m
这样只要a1 a2 r1 r2 轮流迭代即可,不用开数组。题目也没说k多大,暗示本题不用开数组。每次更新a1为LCM(a1,a2),r1为m即可。不过注意求x时 http://blog.csdn.net/shifuwawa/archive/2010/06/10/5662314.aspx 看了别人深刻的分析总算有点懂了,估计自己敲还是有点困难的
*/
#include <iostream>
#include <cstdio>
using namespace std;
__int64 x,y,t;
__int64 extend_gcd(__int64 a,__int64 b)   //return  gcd(a,b) 得到x,y
{
if(b == 0)
{
x = 1;
y = 0;
return a;
}
else
{
__int64 temp = extend_gcd(b,a%b);
t = x; x = y;
y = t - a/b*y;
return temp;
}
}
int main()
{
__int64 a1,a2,r1,r2,c,gcd,temp;
bool yes;
int n;
while(scanf("%d",&n) != -1)
{
yes = false;
scanf("%I64d %I64d",&a1 ,&r1);
for(int i=0 ;i<n-1 ;i++)
{
scanf("%I64d %I64d",&a2 ,&r2);
if(yes)
continue;
c = r2 - r1;
gcd = extend_gcd(a1,a2);
if(c%gcd != 0)
{
yes = true;
continue;
}
temp = a2/gcd;
x = (c/gcd*x % temp + temp)%temp;
r1 = a1*x + r1;
a1 = a1*a2/gcd;
}
if(yes)
printf("-1/n");
else
printf("%I64d/n",r1);
}
return 0;
}
 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  算法 扩展 each 2010 c
相关文章推荐