前言:
复习一下数论(部分)
裴蜀定理
结论:
\(∀a,b∈Ζ\),设\(d=gcd(a,b)\) ,则\(∃x,y\)使得\(ax+by=d\)
推论:
- \(ax+by=m\)有解,当且仅当\(d|m\)
- 若\(gcd(a,b)=1\),则存在\(x,y\)使得\(ax+by=1\)
- 对于\(n\)个数\(a_1,a_1,...a_n\)设\(d=gcd\{a_1,a_2,..a_n\}\),则方程$a_1 x_1 + a_2 x_2 + ... +a_n x_n =m $ 有解,当且仅当\(d|m\)
扩展欧几里得(exgcd)
结论:
若\(x_0,y_0\)满足\(ax+by=d\),则
的\(x,y\)也满足上式,
且这些\(x,y\)是所有可能的解
求解:
代码:
$code$
inline void exgcd(int a,int b,int &x,int &y){if(!b) x=1,y=0;else exgcd(b,a%b,y,x),y-=a/b*x;
}
应用:
- 求逆元
- 求解线性同余方程
中国剩余定理(CRT)
自己家的东西还是学学比较好,其实别家的也得学
求解方程
求解:
设 \(m=∏_{i=1}^n m_i,M_i=\frac{m}{m_i},t_i\) 满足 $M_i t_i≡1 ~ (mod ~ m_i) $
则\(ans=∑_{i=1}^n a_i M_i t_i\)
证明:
∵ \(M_i=\frac{m}{m_i}\)
∴ \(∀k≠i,M_i t_i ≡ 0 ~ ( ~ mod ~ m_i ~ )\) (因为\(M_i\)是除\(m_i\)以外的模数的倍数)
∵ $M_i t_i≡1 ~ ( ~ mod ~ m_i ~ ) $
∴ $ a_i M_i t_i ≡ a_i ~ ( ~ mod ~ m_i ~ )$
过程:
其实就是把\(n\)个方程经过\(n-1\)次合并,最后成为一个方程求解就好了。
首先提出两个方程
将其转化为
易得
整理得
然后用扩展欧几里得求出\(k_1\)和\(-k_2\),当且仅当 \(gcd(m_1 , m_2) ~ | ~ a_2 - a_1\) 时有解。
设$$d=gcd(m_1 , m_2)$$
设$$m_1 k_1= A,lcm=M$$
因此,
合并为
在与下面的方程继续合并,最后合并为一个方程$$x = k M + A$$
此时,\(x\)的最小正整数解为 \(A ~ mod ~ M\) 的正余数。
代码:(【模板】中国剩余定理(CRT)/ 曹冲养猪)
$code$
#include<bits/stdc++.h>
using namespace std;
#define int __int128
const int N=20;
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch-'0');ch=getchar();}return x*f;}
inline void write(int x){if(x<0)x*=-1,putchar('-');if(x>9)write(x/10);putchar(x%10+'0');return;}
int m=1,a[N],b[N],n,k,s;
int exgcd(int a,int b,int &x,int &y){if(!b){x=1;y=0;return a;}int r=exgcd(b,a%b,x,y);int t=x;x=y;y=t-a/b*y;return r;
}
signed main(){n=read();for(int i=1;i<=n;i++){a[i]=read();b[i]=read();m*=a[i];}for(int i=1;i<=n;i++){k=m/a[i];int x,y;exgcd(k,a[i],x,y);s=s+k*b[i]%m*x%m;}write((s%m+m)%m);return 0;
}
扩展中国剩余定理(exCRT)
...
扩展卢卡斯定理(exLucas)
...