扩展中国剩余定理
中国剩余定理可以用来求解下面的线性同余方程组 做法如下:
- 计算所有的模数的积为M
- 计算第i个方程的
- 求再模下的逆元
扩展中国剩余定理:
模数不一定互质 思路: 先考虑2个式子: 等价变形得: 则: 移项得
扩展欧几里得算法: 用来求的一组整数解 当时,显然是一组解 当时, 所以: 通解:
求不定方程的一组整数解: 如果,一定有整数解,否则没有 可以先用扩展欧几里得算法求出的一组解,在乘以,即可得到原方程的特解。
因此上式的 可以看成 有解与无解的判定:如果,一定有整数解,否则没有 如果有解:使用扩展欧几里得算法求出对应的解为,再将其扩大倍 则通解,因为要求最小的,可以使用求出,其中 接着考虑将一开始选择的两个式子进行合并:,是满足方程的最小整数 带入求出的,则 即 可以看成一个新的方程 其中a=\frac{a_1*a_2}{d}$$m=a_1*k_1+m_1
代码
/**
⠀⠀⠀⠀⠰⢷⢿⠄
⠀⠀⠀⠀⠀⣼⣷⣄
⠀⠀⣤⣿⣇⣿⣿⣧⣿⡄
⢴⠾⠋⠀⠀⠻⣿⣷⣿⣿⡀
0 ⠀⢀⣿⣿⡿⢿⠈⣿
⠀⠀⠀⢠⣿⡿⠁⠀⡊⠀⠙
⠀⠀⠀⢿⣿⠀⠀⠹⣿
⠀⠀⠀⠀⠹⣷⡀⠀⣿⡄
⠀⠀⠀⠀⣀⣼⣿⠀⢈⣧
*/
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define debug(x) cout<<"a["<<x<<"]="<<a[x]<<endl;
#define pr(x) cout<<x<<endl;
#define ct(x) cout<<x<<" ";
#define IOS ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
typedef long long ll;
typedef pair<int, int> PII;
const int INF = 0x3f3f3f3f;
const int N = 1e5 + 10;
ll exgcd(ll a, ll b, ll &x, ll &y) {
if (!b) {
x = 1, y = 0;
return a;
}
ll d = exgcd(b, a % b, y, x);
y -= a / b * x;
return d;
}
int main() {
//IOS;
#ifndef ONLINE_JUDGE
freopen("/Users/houyunfei/CLionProjects/MyCppWorkSpace/test.in", "r", stdin);
freopen("/Users/houyunfei/CLionProjects/MyCppWorkSpace/test.out", "w", stdout);
#endif
int n;
cin >> n;
bool flag = true;
ll a1, m1;
cin >> a1 >> m1;
for (int i = 0; i < n - 1; i++) {
ll a2, m2;
cin >> a2 >> m2;
ll x, y;
ll d = exgcd(a1, a2, x, y);
if ((m2 - m1) % d)//不能整除则无解
{
flag = false;
break;
}
//此时的x,y为 a1x+a2y=gcd(a1,a2)=d的解,需要扩大
x *= (m2 - m1) / d;
//通解为:x =x0+a2/d*k;x0为上面求出来的特解
ll t = a2 / d;
x = (x % t + t) % t;
//将两组合并,这里得先变m1,因为m1里面包含了a1,如果
//先变a1会影响m1
m1 = a1 * x + m1;
a1 = abs(a1 / d * a2);
}
if (flag) {
pr((m1 % a1 + a1) % a1)
} else {
pr(-1)
}
return 0;
}