您的位置:首页 > 其它

poj 2891 Strange Way to Express Integers 扩欧解模线性方程

2017-07-14 22:31 639 查看
题意:k对数(a,r)问是否能找到m%ai=ri.能找到输出最小的m,否则输出-1

思路:

m%a1=r1 (1

m%a2=r2 (2

m%a3=r3 (3



m%ak=rk

a,r均为任意输入。不能直接用中国剩余定理。

将1,2方程联立 得a1*x+a2*y=r2-r1

用exgcd求出最小正整数解x0。通解为X=x0+k*(a2/d)   d=gcd(a1,a2) 直接记得结论。

代入1方程化简:a1*x0+k*(a1*a2/d)+r1=m;这样就合并了1,2方程。

类似的再与3联立得

a3*x+(a1*a2/d)*k=r3-(a1*x0+r1) exgcd继续求解。如果中间出现无解的情况,则不存在满足条件的m,重复这个过程。

我的直观理解:

m=r1 (moda1)

m=r2 (moda2)

任意两个符合上面两个式子的解m1,m2

对两个方程i=1,2

M1-m2=r1-r1=0(mod ai)

可以看出它们的差m1-m2即被a1整除,又被a2整除。

所以任意两个解相差k*lcm(a1,a2),k为整数

这样我们可以把m1当任意解(这两个方程得的任意解),

m2可以用扩欧解出一个x,代入第一个方程得到一个m解

 m1=k*lcm(a1,a2)+m2

 m2=a1*x+r1

这样两个方程就合并成一个方程

m=k*lcm(a1,a2)+a1*x+r1

化成与上面相同的形式

m=a1*x+r1(mod(lcm(a1,a2))

如果就没有式子了,答案就是m2=a1*x+r1

如果还有式子继续拿这个新式子与第三个式子合并成同样的形式。

#include<cstdio>
#define ll long long
using namespace std;
const int maxn = 1e5;
int a[maxn],r[maxn];
void exgcd(ll a,ll b,ll &d,ll &x,ll &y)
{
if(!b)
{
d=a;
x=1;
y=0;
}
else
{
exgcd(b,a%b,d,y,x);
y-=x*(a/b);
}
}
int main()
{
int k;
//	freopen("in.txt","r",stdin);
while(~scanf("%d",&k))
{
ll a1,a2,r1,r2,d,x,y;
bool flag=true;
scanf("%lld%lld",&a1,&r1);
for(int i=1;i<k;i++)
{
c91e
scanf("%lld%lld",&a2,&r2);
if(flag==0)continue;
ll a=a1;
ll b=a2;
ll c=r2-r1;
exgcd(a,b,d,x,y);
if(c%d)flag=false;
x=((x*(c/d))%(b/d)+(b/d))%(b/d);//x是一个特解(最小正整数)
r1=a1*x+r1;
a1=a1*(a2/d);//lcm
}
if(!flag)
{
printf("-1\n");
continue;
}
else
{
printf("%lld\n",r1);
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: