luoguP1516 青蛙的约会|数论|同余|扩展欧几里得算法
青蛙的约会|数论|同余|扩展欧几里得算法
为什么这种乐(S)观(B)的青蛙都能网恋,还成功了(我:???????SB青蛙去死8 )
为什么最近一直在做青蛙的题?(我怕是要无限-1s制了????)
Problem
分析
根据题意可得:
青蛙A:
初始位置x,每次跳m
青蛙B:
初始位置y,每次跳n
总长度为L
求相遇时间(如果有解)t
即换成数学表达式:
\[x+m\cdot t \equiv y+n\cdot t \left(mod \ L\right)
\]
根据分析扩展欧几里得算法的步骤:
\[L|\left(x+m\cdot t\right)-\left(y+n\cdot t \right)
\]
=>
\[L|\left(x-y\right)+\left(m-n\right)t
\]
=>
\[\left(x-y\right)+\left(m-n\right)t=kL,k\in Z^{*}
\]
令
\[n-m=a,x-y=b(a>0,b>0)
\]
注意:
如果a<0:
需要把a和b调正:
\[a=-a,b=-b
\]
则
\[a\cdot t+k\cdot L=b
\]
方程有解:
当且仅当
\[gcd\left(a,k\right)|b
\]
如果有解:
则
\[a\cdot t+L\cdot k=gcd\left(a,k\right)
\]
根据扩展欧拉定理得一个解t0
之后对t0进行操作得到t的一个解:
\[t=t_0\cdot \frac{b}{gcd\left(a,k\right)}
\]
再进行调正:
\[t=\left(t\%\frac{L}{d}+\frac{L}{d}\right)\%\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;
}