本文已参与「新人创作礼」活动,一起开启掘金创作之路。
传送门
借此题复习一下中国剩余定理。

题意:
此题可简化成求同余方程的解(a1...an互质):
x mod a1=b1
x mod a2=b2
x mod a3=b3
......
x mod an=bn
直接求出x的值不太现实,于是将问题转化为求以下x1...xn的解:
x1 mod a1=b1
x2 mod a2=b2
x3 mod a3=b3
......
xn mod an=bn
而∑x1xn就是答案,当然,对于每一个xi,我们还需要制定额外的限制条件,以保证∑x1xn可以作为答案:
对于xi,我们需要让它能够整除a1到an中除ai之外的所有数,即:xi必须要是(∏j=1naj)/ai的倍数并且xi mod ai=bi。
首先设prod为∏j=1naj,对于ai,我们来罗列一下它的限制条件:
{xi mod ai=bixi∣(prod/ai)
也就是说,我们要在除了ai之外的所有模数的乘积(即prod/ai)倍数中,找到一个模ai等于bi的数,但在这里我们不选择枚举的方式,而是通过找到prod/ai模ai下的逆元,再乘上模数bi,从而得到xi。
那么,为什么采取这种方式去得到xi?
首先看一下逆元的定义:
设d为a模b下的逆元,则:a∗d≡1(mod b),即:a∗d mod b=1,
此外,要引入一条定理:
若a1 mod b=c,且a2 mod b=c/2,则a1=2∗a2
于是,求出逆元di后,ai∗di mod b=1,而ai∗di∗bi mod bi=bi。
在这题上就是:用prod/ai∗模bi的逆元得到一个prod/ai的倍数且模bi为1的数,再乘上相应的模数bi即可得到一个满足上述限制条件表达式的值。
于是最后的答案就是:∑x1xn,而最小的答案为∑x1xn mod prod
最终答案的表达式为:
x=(∑i=1nprod/ai∗(prod/ai)−1∗bi),其中(prod/ai)−1为(prod/ai)−1模bi下的逆元。
这题的ac代码:
顺便说一下求逆元要用扩展欧几里得求解,费马小定理要求模数为质数,扩欧只要求互质,即逆元存在。
using namespace std
ll a[100010],b[100010]
void exgcd(ll a, ll b, ll &x, ll &y)
{
if (!b)
{
x = 1
y = 0
return
}
exgcd(b, a % b, x, y)
ll temp = x
x = y
y = temp - (a / b) * y
}
int main()
{
int n
cin>>n
ll sum = 1
for(int i = 1
{
cin>>a[i]>>b[i]
sum*=a[i]
}
ll ans = 0
for(int i = 1
{
ll x=0,y=0
exgcd(sum/a[i],a[i],x,y)
ans += sum*b[i]*(x > 0?x:x+a[i])
}
cout<<ans%sum<<endl
}