P4777 题解
2025.8.21 更正一处笔误。
题意解释
给定
n 组非负整数
ai,bi,求解关于
x 的方程组的最小非负整数解:
⎩⎨⎧x≡b1(moda1)x≡b2(moda2)…x≡bn(modan)
数学前置知识
解方程:
⎩⎨⎧x≡b1(moda1)x≡b2(moda2)…x≡bn(modan)
其中
a1,a2,…,an 两两互质。
我们可以构造
M=∏i=1nai 并令
Mk=akM,
yk 是
Mk 在模
ak 意义下的逆元。
此时方程的解
x=∑i=1naiMiyi。
这便是中国剩余定理(CRT)。
但中国剩余定理有一个条件:要求
a1,a2,…,an 两两互质。
这也没有关系,我们可以任取
{x≡bi(modai)x≡bj(modaj) 并计算出特解
x0,此时就会有通解
x=x0−klcm(ai,aj),也就是说这两个方程会合并成一个方程
x≡x0(modlcm(ai,aj)),这便是扩展中国剩余定理的核心思想。
证明
取
{x≡bi(modai)x≡bj(modaj)。
转化成一般形式
{k1ai+bi=xk2aj+bj=x。
移项得
k1ai−k2aj=bj−bi。
此时我们已知
ai,aj,bi,bj,但未知
k1,k2。
将其看作关于
k1,k2 的不定方程,根据裴蜀定理,若
gcd(ai,aj)∤(bi−bj),则方程无解。
对于有解的情况,用扩展欧几里得算法求出特解,并推出通解:
令
g=gcd(ai,aj),d1=gai,d2=gaj。
代入原方程得:
k1d1g−k2d2g=bj−bi
∵g=0∴k1d1−k2d2=gbj−bi∵k1d1−k2d2∈Z∴g∣(bj−bi)
设特解为
ω1,ω2,则
k1,k2 的特解为:
⎩⎨⎧k1=gbj−biω1k2=−gbj−biω2
求得特解
x0=k1ai+bi=gbj−biω1+bi。
原方程通解为
x=x0−klcm(ai,aj),k∈Z。
证毕。
算法流程
- 初始化等价方程 x≡0(mod1)(即 A=1,B=0)
- 依次合并每个方程 x≡bi(modai):
- 计算 g=gcd(A,ai)。
- 用扩展欧几里得算法解 A⋅x+ai⋅y=g。
- 若 g∤(B−bi),则无解。
- 计算特解 x0=B−A⋅x⋅gB−bi。
- 更新模数 A=gA⋅ai。
- 更新余数 B=x0modA。
- 最终解为 BmodA(取最小非负整数)。
AC 代码
CPP#include<bits/stdc++.h>
#define ll __int128
using namespace std;
const int N=1e5+5,M=1e5+5;
int n;
ll A=1,B=0,x,y;
ll exgcd(ll a,ll b,ll &x,ll &y){
if(!b){
x=1,y=0;
return a;
}
else{
ll aa=exgcd(b,a%b,y,x);
y-=a/b*x;
return aa;
}
}
int main(){
cin>>n;
for(int i=1;i<=n;i++){
long long a,b;
cin>>a>>b;
ll gd=exgcd(A,a,x,y);
x=(B-b)/gd*x;
B=B-A*x;
A=a/gd*A;
B=(B%A+A)%A;
}
long long ans=(B%A+A)%A;
cout<<ans<<"\n";
return 0;
}