中国剩余定理
实质就是解 次互质的方程,然后分别乘以他们的取模剩余量,然后相加得到答案,这里就不展开叙述。
typedef long long ll;
const int N = 1e3 + 10;
int a[N], b[N], n;
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;
return ;
}
void solve() {
ll m = 1, x, y, ans = 0;
for(int i = 1; i <= n; i++)
m *= b[i];
for(int i = 1; i <= n; i++) {
ll t = m / b[i];
exgcd(t, b[i], x, y);
ans = (ans + x * t * a[i]) % m;
}
ans = (ans + m) % m;
printf("%lld\n", ans);
}
int main() {
scanf("%d", &n);
for(int i = 1; i <= n; i++)
scanf("%d %d", &a[i], &b[i]);//a[i]是余数,b[i]是模数。
solve();
return 0;
}
中国剩余定理拓展
思路
我们规定 时余数, 是模数。
显然对于一个方程我们可以直接得到 ,用这个答案去求解第二个方程,解显然可以描述为 ,所以第二个方程的解可以如下推理:
所以我们只要解的 就行,无非就是做一次 嘛,得到
如果继续拓展下去,我们显然有 ,也就是把上面推导的式子换成前 项的 。
P4777 【模板】扩展中国剩余定理(EXCRT)
裸题。
/*
Author : lifehappy
*/
// #pragma GCC optimize(2)
// #pragma GCC optimize(3)
// #include <bits/stdc++.h>
#include <cstdio>
#include <iostream>
#include <stdlib.h>
#include <algorithm>
#include <cmath>
#define mp make_pair
#define pb push_back
#define endl '\n'
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
const double pi = acos(-1.0);
const double eps = 1e-7;
const int inf = 0x3f3f3f3f;
inline ll read() {
ll f = 1, x = 0;
char c = getchar();
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
x = (x << 1) + (x << 3) + (c ^ 48);
c = getchar();
}
return f * x;
}
void print(ll x) {
if(x < 10) {
putchar(x + 48);
return ;
}
print(x / 10);
putchar(x % 10 + 48);
}
const int N = 1e5 + 10;
ll a[N], b[N];
int n;
ll quick_mult(ll a, ll b, ll mod) {
ll ans = 0;
while(b) {
if(b & 1) ans = (ans + a) % mod;
b >>= 1;
a = (a + a) % mod;
}
return ans;
}
ll ex_gcd(ll a, ll b, ll & x, ll & y) {
if(!b) {
x = 1, y = 0;
return a;
}
ll gcd = ex_gcd(b, a % b, x, y);
ll temp = x;
x = y;
y = temp - a / b * y;
return gcd;
}
int main() {
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
// ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
n = read();
for(int i = 1; i <= n; i++) a[i] = read(), b[i] = read();
ll ans = b[1], M = a[1];
for(int i = 2; i <= n; i++) {
ll A = M, B = a[i], C = ((b[i] - ans) % a[i] + a[i]) % a[i], x, y;
ll gcd = ex_gcd(A, B, x, y);
B /= gcd;
x = quick_mult(x, C / gcd, B);
ll mod = M * B;
ans = (ans + quick_mult(x, M, mod)) % mod;
M = mod;
}
printf("%lld\n", ((ans % M) + M) % M);
return 0;
}