11.19鲜花

发布时间 2023-11-19 21:29:19作者: Vsinger_洛天依

第一天学数论

学了学exgcd和逆元

找了普及组OJ上的几道简单题来做

  1. 同余方程

拓展欧几里得板子题

对于形似\(a\times x=1\pmod{b}\)的同余方程

可以转化成\(a\times x+b\times y=1\)

然后就可以通过\(exgcd\)直接求解

点击查看代码
#include<bits/stdc++.h>
#define lC q<<1
#define rC q<<1|1
#define int long long
#define INF 0x66ccff0712
#define endl "\n"
#define maxm 0x66ccff
#define maxn 0x6cf 
#define mid ((l+r)>>1)
#define void inline void
using namespace std;
inline int read(){
    int s = 0,w = 1;char ch = getchar();
    while(ch<'0'||ch>'9'){ if(ch == '-') w = -1;ch = getchar();}
    while(ch>='0'&&ch<='9'){ s = s*10+ch-'0';ch = getchar();}
    return s*w;
}
inline int gcd(int a,int b){
    return __gcd(a,b);
}
inline int exgcd(int a,int b,int &x,int &y){
    if(b==0){
        x=1,y=0;
        return a;
    }
    int d=exgcd(b,a%b,x,y);
    int z=x;x=y,y=z-y*(a/b);
    return d;
}
inline int exmod(int a,int b){
    int d,x,y;
    d=exgcd(a,b,x,y);
    if(d==1) return(x%b+b)%b;
    else return -1;
}
signed main(){
#ifndef ONLINE_JUDGE
    freopen("1.in","r",stdin);
    freopen("1.out","w",stdout);
#endif
    int a,b;
    cin>>a>>b;
    cout<<exmod(a,b);
}
  1. 青蛙的约会

对于步数\(t\),可以推出式子

\[(x+m*t)-(y+n*t)=p*L \]

其中\(p\)为青蛙\(1\)和青蛙\(2\)的圈数差

然后转化

\[(x+m*t)-(y+n*t)=p*L \]

\[x+m*t-y-n*t=p*L \]

\[(m-n)*t-L*p=y-x \]

\[(n-m)*t+L*p=x-y \]

我们可以发现,这是一个同余方程

\[a*x+b*y=d\ \ \ \ (a=\{n-m\},b=\{L\},d=\{x-y\}) \]

题目是求\(t\)的一组最小解

先用\(exgcd\)求出一组解\(t_0,p_0\)

\[(n-m)*t_0+L*p_0=gcd(n-m,L) \]

\[(n-m)*t_0*\frac{x-y}{gcd(n-m,L)}+L*p_0*\frac{x-y}{gcd(n-m,L)}=gcd(n-m,L)*\frac{x-y}{gcd(n-m,L)} \]

\[(n-m)*t_0*\frac{x-y}{gcd(n-m,L)}+L*p_0*\frac{x-y}{gcd(n-m,L)}=x-y \]

可以得出,最小解为\(t_0*\frac{x-y}{gcd(n-m,L)}\),但是负数不是没可能

\[(n-m)*(t_0*\frac{x-y}{gcd(n-m,L)}-L*N)+L*(p_0*\frac{x-y}{gcd(n-m,L)}-(n-m)*N)=x-y\ \ \ (\exists\ N\in \R) \]

所以,我们可以得到解为

\[(t_0*\frac{x-y}{gcd(n-m,L)}\mod L+L)\mod L \]