CRT----中国剩余定理
题意:给你n个式子$x equiv b_i (mod a_i)$,求x的最小正整数解(CRT裸题)
中国剩余定理求解
考虑每一个式子i$left{egin{aligned}x equiv 0 (mod a_1) \ x equiv 0 (mod a_2) \ x equiv 0 (mod a_2) \ .\.\.\ x equiv 1 (mod a_i) \.\.\.\ x equiv 0 (mod a_n)end{aligned} ight.$
可以求出每个式子的解$x_i$,则$ans=sum{x_i*b_i}(mod Pi{a_i})$
那么,考虑怎么求解每一个式子i
首先,对于每一个j$x_i equiv 0 (mod a_j)$
不难得出$x_iequiv 0 (mod Pi{a_j})$
我们令$N=Pi{a_j}$
则$x_iequiv 0 (mod frac{N}{a_i})$
也就是说$x_i=k*frac{N}{a_i}$
而对于那个特殊的式子i$x_i equiv 1 (mod a_i)$
可以得出$x_i=p*a_i+1$
因此$x_i=p*a_i+1=k* frac{N}{a_i}$
$p*a_i+1=k* frac{N}{a_i}$
$k* frac{N}{a_i}-p*a_i=1$
有没有get到什么》》??
显然的exgcd啊
因此,k与p就得到了
反推回去,x也得到了
最后,ans就求出来了
#include<cstdio> #include<iostream> #include<cstring> #include<cctype> #include<algorithm> using namespace std; #define int long long #define olinr return #define _ 0 #define love_nmr 0 #define DB double inline int read() { int x=0,f=1; char ch=getchar(); while(!isdigit(ch)) { if(ch=='-') f=-f; ch=getchar(); } while(isdigit(ch)) { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); } return x*f; } inline void put(int x) { if(x<0) { x=-x; putchar('-'); } if(x>9) put(x/10); putchar(x%10+'0'); } int n; inline void exgcd(int a,int b,int &x,int &y) { if(!b) { x=1; y=0; return; } exgcd(b,a%b,x,y); int t=x-a/b*y; x=y; y=t; } int bb[20]; int aa[20]; int ans; int N=1; inline int work(int pos) { int p,k; exgcd(N/aa[pos],aa[pos],p,k); int ansx=p*(N/aa[pos]); return (ansx*bb[pos])%N; } signed main() { n=read(); for(int i=1;i<=n;i++) { aa[i]=read(); bb[i]=read(); } for(int i=1;i<=n;i++) N*=aa[i]; for(int i=1;i<=n;i++) (ans+=work(i))%=N; put(ans>0? ans:ans+N); olinr ~~(0^_^0)+love_nmr; }