关于拓展欧几里得算法
运用拓展欧几里得算法,可以求出GCD(a,b),并且求出一组满足AX+BY=GCD(A,B)。
1.当B==0时,X=1,Y=0等式成立
2.当B>0时,有
BX'+(A mod B)Y'=GCD(B,A mod B)=GCD(A,B)
可以通过变形得到
AY'+B(X'-A/B*Y')=GCD(A,B)
由此可得 X=Y‘,Y=X'-A/B*Y',当GCD(B,A mod B)进行至B==0时到达出口。
通解为 X+B/GCD(A,B)*C,Y+A/GCD(A,B)*C。为任意整数。
题意:
一直位于x速度为m的青蛙1与位于y速度为n青蛙2往同一个方向跳圈,圈长为L,问什么时候可以相遇。
思路:
依题意可列方程:(x+m*t)-(y+n*t)=p*L
整理得C*((n-m)*t+L*p)=x-y,C为任意正整数,由此可得如果GCD(n-m,L)*C=x-y,则符合拓展欧几里得方程的形式,此时t有解。
运用拓展欧几里得公式可得到t的一个解,通过X+B/GCD(A,B)*C找到最小的t的解,输出。
#include <iostream>
using namespace std;
typedef long long LL;
LL exgcd(LL a,LL b,LL &x,LL &y)
{
if(b==0)
{
x=1;
y=0;
return a;
}
else
{
LL r=exgcd(b,a%b,y,x);
y-=x*(a/b);,
return r;
}
}
int main()
{
LL x,y,m,n,L;
LL A,B,X,Y,c;
while(cin>>x>>y>>m>>n>>L)
{
A=n-m;
B=L;
c=x-y;
LL r=exgcd(A,B,X,Y);
if(c%r!=0)//c%r!=0的情况不符合拓展GCD的形式,此时t无解
{
cout<<"Impossible\n";
continue;
}
X*=c/r;
Y*=c/r;
LL ans=X*r/B;//x=x0+B/GCD(A,B)*C,假设x为0,可得最接近0的解,此时C=x0/B/GCD(A,B)
ans=X-ans*(B/r);//此时ans为最接近0的解
if(ans<0)//为负数时变成最小的正数
ans+=B/r;
cout<<ans<<endl;
}
return 0;
}