题目链接
China residual theorem,故函数写为Crt
参考博客
用处
{ x % a 1 = p 1 x % a 2 = p 2 … … x % a n = p n \begin{cases} x\%\,a_1=p_1\\ x\%\,a_2=p_2\\ ……\\ x\%\,a_n=p_n\\ \end{cases} ⎩⎪⎪⎪⎨⎪⎪⎪⎧x%a1=p1x%a2=p2……x%an=pn
其中 a 1 , a 2 , … … a n a_1,a_2, ……a_n a1,a2,……an 互质,(注意这个使用条件)求解x。
基础定理
定理1:两个数相加,如果存在一个加数,不能被整数a整除,那么它们的和,就不能被整数a整除。
定理2:两数不能整除,若除数扩大(或缩小)了几倍,而被除数不变,则其商和余数也同时扩大(或缩小)相同的倍数(余数必小于除数)。
算法步骤
(用下面这个样例进行演示)
3
3 2
5 3
14 1
1、求出最小公倍数
lcm=3*5*14=210
2.为每组数(a,b)找到一个基础数满足 (lcm/a)%a=b
(1)210÷3=70
70÷3=33…1,故基础数为70*2=140
(2)210÷5=42
42÷5=8…2
5/2=2……1,当前余数1是要找余数3的因子,故可以溯回了。
则1=5-2 * 2=5-2 *(42-8*5)=-2 * 42+17 * 5 (仔细想一下这个哦 🚡)
(这个是不是就是求解ax+by=gcd(a,b),又因为互质故而gcd(a,b)=1, 然后得到ax,再利用定理2,余数1扩大3倍,则被除数也扩大3倍,得到基础数ax*3=42*(-2)*3=-252)
(3)210÷14=15
15÷14=1…1,故基础数为15
总结:故而这一步其实可以用扩展欧几里得完成,在(2)比较明显体现。
3.把得到的基础数加和(注意:基础数不一定就是正数)
140-252+15=-97
4.找到符合条件的最小k值
k=(-97+lcm)%lcm=113
代码
#include<cstdio>
#include<algorithm>
#include "bits/stdc++.h"
using namespace std;
typedef long long ll;
const int maxn=1e2+10;
void exgcd(ll a,ll b,ll& x,ll& y,ll& g) {
if(b==0)x=1,y=0,g=a;
else exgcd(b,a%b,y,x,g),y-=x*(a/b);
}
ll a[maxn],p[maxn];
int n;
// 中国剩余定理China residual theorem
ll Crt() {
ll lcm=1,ans=0;
for(int i=1;i<=n;++i)lcm*=a[i];
for(int i=1;i<=n;++i)
{
ll now=lcm/a[i],x,y,g;
exgcd(now,a[i],x,y,g);
ans=(ans+now*x*p[i])%lcm;
}
return (ans+lcm)%lcm;
}
int main(void) {
// freopen("in.text","r",stdin);
scanf("%d",&n);
for(ll i=1; i<=n; ++i)scanf("%lld%lld",&a[i],&p[i]);
printf("%lld\n",Crt());
return 0;
}