数论(扩欧+线性同余+裴蜀定理+一元一次不定方程)学习心得 + P1516 青蛙的约会 做题记录
相信大家已经对这三个东西了如指掌了,接下来我们来康一道例题:
P1516 青蛙的约会
我们设碰面需要的时间(也就是要求解的东西)是 \(t\) ,他们之间碰面的时候走的距离差了 \(k\) 圈,那么有:
\[tm+x-tn-y=kL
\]
推到一下可以得到:
\[\begin{align}
tm-tn-kL&=y-x\\
t(m-n)-kL&=y-x\\
\end{align}
\]
这是一个线性同余方程,但是不能保证 \(m-n\) 和 \(L\) 互质,所以我们向等式两边同时除以 \(m-n\) 和 \(L\) 的 \(\gcd\) \(g\)
\[\begin{align}
t \cdot \frac{m-n}{g}-k \cdot \frac{L}{g} &= \frac{y-x}{g} \\
t \cdot \frac{m-n}{g}&\equiv \frac{y-x}{g} \; (\text{mod}\ \frac{L}{g})\\
t &\equiv \frac{y-x}{g} \cdot \frac{g}{m-n} \; (\text{mod}\ \frac{L}{g})\\
t &\equiv \frac{y-x}{m-n}\;(\text{mod}\ \frac{L}{g})
\end{align}
\]
令 \(ysx = y-x\) , \(msn = m-n\) ,\(Ldg = \frac{L}{g}\) (这一步主要是为了好看(误)),那么就有
\[t\equiv\frac{ysx}{msn}\%Ldg
\]
哈哈,真简洁,所以我们就可以直接算啦
注意记得判 \(ysx\) 不能整除 \(g\) 和 \(msn\) 是负数的情况
#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll exgcd(ll a,ll b,ll &x,ll &y){
ll xd=0,yd=1,q;x=1,y=0;
while(b){
q=a/b;
tie(a,b,x,y,xd,yd)=
make_tuple(b,a-q*b,xd,yd,x-xd*q,y-yd*q);
}
return a;
}
ll inv(ll x,ll P){
ll a,b;int f=0;
if(x<0)x=-x,f=1;
exgcd(x,P,a,b);
if(f==1)return -a;
return a;
}
ll a,b,m,n,g,k,L,t,x,y,ysx,msn,Ldg;
int main(){
scanf("%lld %lld %lld %lld %lld",&x,&y,&m,&n,&L);
ysx=(y-x+L)%L;
msn=m-n;
g=__gcd(msn,L);
Ldg=abs(L/g);
if(ysx%g==0){
t=(ysx*inv(msn,Ldg)%Ldg+Ldg)%Ldg;
printf("%lld",t);
}else{
printf("Impossible");
}
return 0;
}