青蛙的约会|数论|同余|扩展欧几里得算法
为什么这种乐(S)观(B)的青蛙都能网恋,还成功了(我:???????SB青蛙去死8 )
为什么最近一直在做青蛙的题?(我怕是要无限-1s制了????)
Problem
分析
根据题意可得:
青蛙A:
初始位置x,每次跳m
青蛙B:
初始位置y,每次跳n
总长度为L
求相遇时间(如果有解)t
即换成数学表达式:
[x+mcdot t equiv y+ncdot t left(mod L
ight)
]
根据分析扩展欧几里得算法的步骤:
[L|left(x+mcdot t
ight)-left(y+ncdot t
ight)
]
=>
[L|left(x-y
ight)+left(m-n
ight)t
]
=>
[left(x-y
ight)+left(m-n
ight)t=kL,kin Z^{*}
]
令
[n-m=a,x-y=b(a>0,b>0)
]
注意:
如果a<0:
需要把a和b调正:
[a=-a,b=-b
]
则
[acdot t+kcdot L=b
]
方程有解:
当且仅当
[gcdleft(a,k
ight)|b
]
如果有解:
则
[acdot t+Lcdot k=gcdleft(a,k
ight)
]
根据扩展欧拉定理得一个解t0
之后对t0进行操作得到t的一个解:
[t=t_0cdot frac{b}{gcdleft(a,k
ight)}
]
再进行调正:
[t=left(t\%frac{L}{d}+frac{L}{d}
ight)\%frac{L}{d}
]
Code
#include <cstdio>
#include <iostream>
#define ll long long
using namespace std;
ll x,y,m,n,l,t,k;
ll exgcd(ll a,ll b,ll &x,ll &y){
if(b==0){
x=1,y=0;
return a;
}
int d=exgcd(b,a%b,x,y);
int tmp=x;x=y;y=tmp-(a/b)*y;
return d;
}
int main(){
scanf("%lld%lld%lld%lld%lld",&x,&y,&m,&n,&l);
ll a=n-m,b=x-y;
if(a<0) a=-a,b=-b;//修正为正数
ll d=exgcd(a,l,t,k);
if(b%d==0){
t=t*b/d;//获得一个解
t=(t%(l/d)+(l/d))%(l/d);//修正负数
printf("%lld",t);
}else printf("Impossible");
return 0;
}