数论(扩欧+线性同余+裴蜀定理+一元一次不定方程)学习心得 + P1516 青蛙的约会 做题记录

这一篇讲非递归扩欧讲得好 - OI Wiki

裴蜀定理 - OI Wiki

线性同余方程 - OI Wiki)

相信大家已经对这三个东西了如指掌了,接下来我们来康一道例题:

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;  
}
posted @ 2023-10-13 12:56  DZhearMins  阅读(7)  评论(0编辑  收藏  举报