您的位置:首页 > 其它

POJ2891 Strange Way to Express Integers 线性同余方程组

2016-09-28 20:23 423 查看
就是给你N个同余方程x%a=b

求最小的正整数解x,因为a不互质,所以只能一个一个求,

同时算拓欧的时候也可能会出现无解的情况,无解输出-1(但是要记得剩下的输完……)

首先对于

x%m1=a1 与 x%m2=a2两个同余方程

x=m1*x1+a1=m2*x2+a2 得到 m2*x2-m1*x1=a1-a2

这时候就可以通过拓欧求出x2的最小正整数解

同时求出x的一个最小正整数解,而这时如果给x增加(或减少)m1与m2的共同倍数,也是x的一个解 (这个为什么自己思考,很容易)那么又可以将这两个方程合并成一个方程 x1%lcm(m1,m2)=x

这样就可以A了

代码:

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
LL gcd(LL x,LL y){return y==0?x:gcd(y,x%y);}
LL exgcd(LL &x,LL &y,LL a,LL b)
{
if(b==0)
{
x=1;y=0;
return a;
}
LL d=exgcd(x,y,b,a%b);
LL px=x;
x=y;
y=px-a/b*y;
return d;
}
LL n,k,ans;
LL a1,m1,a2,m2;
LL getans(LL a,LL b,LL c)
{
LL x,y;
LL d=exgcd(x,y,a,b);
if(c%d!=0)return -1;
x=x*(c/d);
return (x%b+b)%b;
}
int main()
{
while(scanf("%lld",&k)==1&&k)
{
LL flag=0;
scanf("%lld%lld",&m1,&a1);
if(k==1)ans=a1;
for(LL i=2;i<=k;i++)
{
scanf("%lld%lld",&m2,&a2);
if(flag)continue;
ans=getans(m2,m1,a1-a2);
if(ans==-1)
{
flag=1;
continue;
}
a1=a2+m2*ans;
m1=m1*m2/gcd(m1,m2);
a1=(a1%m1+m1)%m1;
}
if(flag)puts("-1");
else printf("%lld\n",a1);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  poj