题意
题目描述
给定(n)组非负整数(a_i, b_i),求解关于(x)的方程组
[egin{cases} x equiv b_1 ({
m mod} a_1) \ xequiv b_2 ({
m mod} a_2) \ ... \ x equiv b_n ({
m mod} a_n)end{cases}$$的最小非负整数解。
## 输入输出格式
### 输入格式:
输入第一行包含整数$n$。
接下来$n$行,每行两个非负整数$a_i, b_i$。
### 输出格式:
输出一行,为满足条件的最小非负整数$x$。
## 输入输出样例
### 输入样例#1:
3
11 6
25 9
33 17
### 输出样例#1:
809
## 说明
$n leq 10^5, 1 leq a_i leq 10^{12}, 0 leq b_i leq 10^{12}, b_i < a_i$,保证答案不超过$10^{18}$。
请注意程序运行过程中进行乘法运算时结果可能有溢出的风险。
数据保证有解
# [niiick](https://www.luogu.org/blog/niiick/solution-p4777)的题解
问题
求解同余方程组
]
left{egin{aligned}xequiv a_1(mod m_1) quad xequiv a_2(mod m_2) quad xequiv a_3(mod m_3) quad ...quadxequiv a_k(mod m_k) quadend{aligned} ight.
[其中$m_1,m_2,m_3...m_k$为不一定两两互质的整数, 求x的最小非负整数解
求解
假设已经求出前k-1个方程组成的同余方程组的一个解为x
且有$M=prod_{i-1}^{k-1}m_i$(补充:代码实现中用的就是$M=LCM_{i-1}^{k-1}m_i$,显然易证这样是对的,还更能防止溢出,上述是为了先方便理解
则前k-1个方程的方程组通解为$x+i*M(iin Z)$
那么对于加入第k个方程后的方程组
我们就是要求一个正整数t,使得$x+t*M equiv a_k(mod m_k)$
转化一下上述式子得$t*M equiv a_k-x(mod m_k)$
对于这个式子我们已经可以通过扩展欧几里得求解t
若该同余式无解,则整个方程组无解, 若有,则前k个同余式组成的方程组的一个解解为$x_k=x+t*M$
所以整个算法的思路就是求解k次扩展欧几里得
```cpp
#include<bits/stdc++.h>
#define rg register
#define il inline
#define co const
template<class T>il T read(){
rg T data=0,w=1;
rg char ch=getchar();
while(!isdigit(ch)){
if(ch=='-') w=-1;
ch=getchar();
}
while(isdigit(ch))
data=data*10+ch-'0',ch=getchar();
return data*w;
}
template<class T>il T read(rg T&x){
return x=read<T>();
}
typedef long long ll;
co int maxn=1e5+1;
int n;
ll ai[maxn],bi[maxn];
ll mul(ll a,ll b,ll mod){
ll re=0;
while(b){
if(b&1) re=(re+a)%mod;
a=(a+a)%mod;
b>>=1;
}
return re;
}
ll exgcd(ll a,ll b,ll&x,ll&y){
if(b==0) {x=1,y=0;return a;}
ll gcd=exgcd(b,a%b,x,y);
ll z=x;x=y;y=z-y*(a/b);
return gcd;
}
ll excrt(){
ll x,y;
ll M=bi[1],ans=ai[1];
for(int i=2;i<=n;++i){
ll a=M,b=bi[i],c=(ai[i]-ans%b+b)%b;
ll gcd=exgcd(a,b,x,y),bg=b/gcd;
if(c%gcd) return -1;
x=mul(x,c/gcd,bg);
ans+=x*M;
M*=bg;
ans=(ans%M+M)%M;
}
return ans;
}
int main(){
// freopen(".in","r",stdin),freopen(".out","w",stdout);
read(n);
for(int i=1;i<=n;++i) read(bi[i]),read(ai[i]);
printf("%lld
",excrt());
return 0;
}
```]