扩展欧几里得算法

来源:互联网 发布:淘宝运营计划表 编辑:程序博客网 时间:2024/04/29 19:37
扩展欧几里得算法:对于不完全为0的非负整数n,m,gcd(n,m)表示n,m的最大公约数,必然存在整数n,m使得gcd(n,m)=nx+my。

假设n>m,当m=0时,gcd(n,m)=n,这个时候x=1,y=0;

其他情况:设n*x1+m*y1=gcd(n,m),m*x2+(n mod m)*y2=gcd(m,n%m);由欧几里得算法有:gcd(n,m)=gcd(m,n%m);

则有:n*x1+m*y1 = m*x2+(n mod m)*y2 = m*x1+(n-(n/m)*m)*y2 = m*y2+n*y2-(n/m)*m*y2,所以:x1=y2,y1=x2-(n/m)*y2。扩展欧几里得的模板为:

#define __int64 long long__int64 ExGcd(__int64 n,__int64 m,__int64 &x,__int64 &y)//nx+my=gcd(n,m);{   if(m==0) {x=1,y=0;return n;}//返回的是n,m的最大公约数     __int64 value=ExGcd(m,n%m,x,y);    __int64 temp=x;    x=y,y=temp-(n/m)*y;    return value;}

定理1:对于方程a*x+b*y=n,有整数解的充分必要条件是:n%gcd(a,b)==0。

例题1:POJ 1061(青蛙的约会)

假设经过t分钟后能够相遇,那么他们走的距离之差一定是总长度的倍数。那么则有:(a*t+dx)-(b*t+dy)=L*num(其中num为总长度倍数)。所以有:(b-a)*t+L*num=dx-dy。那么

就相当于:nx+my=gcd(n,m)的类型了。也就是说这个方程要有整数解(t,num为未知数),为扩展欧几里得算法。

所以说这个方程要有整数解的话,b-a和L的最大公约数为:dx-dy,即:(dx-dy)%gcd(b-a,L)=0;当不满足这个条件时输出:"Impossible"。

#include<iostream>#include<cstring>#include<cstdio>using namespace std;#define __int64 long long__int64 dx,dy,a,b,L,x,y;__int64 ExGcd(__int64 n,__int64 m,__int64 &x,__int64 &y){   if (m==0) { x=1,y=0; return n; }__int64 temp,val=ExGcd(m,n%m,x,y);    temp=x,x=y,y=temp-(n/m)*y;    return val;}int main(){   while(scanf("%lld%lld%lld%lld%lld",&dx,&dy,&a,&b,&L)!=EOF){   __int64 val=ExGcd(b-a,L,x,y);     L/=val;        if((dx-dy)%val) puts("Impossible");else printf("%lld\n",((dx-dy)/val*x%L+L)%L);}return 0;}


原创粉丝点击