题解:P1495 【模板】中国剩余定理(CRT)/ 曹冲养猪
P1495 【模板】中国剩余定理(CRT)/ 曹冲养猪 题解
题意
试求如下同余方程组的最小非负整数解:
其中,
思路
对于这样模数两两互质的题,可以使用中国剩余定理来求解。什么是中国剩余定理呢?请听我慢慢道来……
首先,由余数的可加性可知,若可以求得以下
此时,便有原方程的解
现在,考虑将每一个方程组拿出来单独求解。我拿第一个方程组讲解:
要求出如上这个方程的解,其实可以再做一步转换,先求出以下这个方程的解:
由余数的可乘性得:
于是便可以按这种方法,求出上面的
所以,设所有的数的乘积为
代码
开了 __int128。
#include<bits/stdc++.h>
#define int __int128
using namespace std;
const int MAXN = 1e5 + 10;
int n;
int a[MAXN] , b[MAXN];
int s;
int exgcd(int a , int b , int &x , int &y) {
if(!b) {
x = 1;
y = 0;
return a;
}
int r = exgcd(b , a % b , x , y);
int t = x;
x = y;
y = t - a / b * y;
return r;
}
inline int read() {
char c = getchar();
int x = 0 , s = 1;
while(c < '0' || c > '9') {
if(c == '-')
s = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
x = x * 10 + c - '0';
c = getchar();
}
return x * s;
}
void write(int x){
if(x > 9)
write(x/10);
putchar(x % 10 | 48);
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
n = read();
int ans = 1;
for(register int i = 1;i <= n;i ++) {
a[i] = read();
b[i] = read();
ans *= a[i];
}
for(register int i = 1;i <= n;i ++) {
int k = ans / a[i];
int x , y;
exgcd(k , a[i] , x , y);
s = s + k * b[i] * x % ans;
}
write((s % ans + ans) % ans);
return 0;
}