中国剩余定理 && 扩展中国剩余定理
一个整数除以三余二,除以五余三,除以七余二,求这个整数。
例题:
一个正整数K,给出K Mod 一些质数的结果,求符合条件的最小的K。例如,K % 2 = 1, K % 3 = 2, K % 5 = 3。符合条件的最小的K = 23。
#include<bits/stdc++.h>
using namespace std;
const int MAX = 1e3 + 10;
struct node{
int p, m;
}s[MAX];
int main(){
int n;
while(scanf("%d", &n) != EOF){
for(int i = 0; i < n; i++)
scanf("%d%d",&s[i].p, &s[i].m);
int ans = s[0].m, temp = 1;
for(int i = 0; i < n-1; i++){
temp *= s[i].p;
while(ans % s[i+1].p != s[i+1].m){
ans += temp;
}
}
printf("%d\n", ans);
}
return 0;
}
扩展中国剩余定理
一个正整数K,给出K Mod 一些数(不一定是质数)的结果,求符合条件的最小的K。例如,K % 2 = 1, K % 3 = 2, K % 5 = 3。符合条件的最小的K = 23。
整个算法的思路就是求解k次扩展欧几里得
#pragma GCC optimize(2)
#include <bits/stdc++.h>
using namespace std;
#define clr(a) memset(a,0,sizeof(a))
#define line cout<<"-----------------"<<endl;
typedef long long ll;
const int maxn = 1e5+10;
const int MAXN = 1e6+10;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9+7;
const int N = 1010;
ll ai[maxn], bi[maxn], n;
ll mul(ll a, ll b, ll mod){
ll res = 0;
while(b > 0){
if(b & 1) res = (res + a) % mod;
a = (a + a) % mod;
b >>= 1;
}
return res;
}
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 tp = x;
x = y; y = tp - a / b * y;
return gcd;
}
ll excrt(){
ll x, y, k;
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;//ax≡c(mod b)
ll gcd = exgcd(a, b, x, y), bg = b / gcd;
if(c % gcd != 0) return -1; //判断是否无解,然而这题其实不用
x = mul(x, c / gcd, bg);//把x转化为最小非负整数解
ans += x * M;//更新前k个方程组的答案
M *= bg;
ans = (ans % M + M) % M;
}
return (ans % M + M) % M;
}
int main(){
scanf("%lld", &n);
for(int i = 1; i <= n; ++i)
scanf("%lld%lld", &bi[i], &ai[i]);
printf("%lld",excrt());
return 0;
}