第一天学数论
学了学exgcd和逆元
找了普及组OJ上的几道简单题来做
拓展欧几里得板子题
对于形似\(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);
}
对于步数\(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
\]