中国剩余定理

中国剩余定理

acwing 204. 表达整数的奇怪方式

题目描述
  给定 2n 个整数 a1,a2,…,an 和 m1,m2,…,mn,求一个最小的非负整数 x,满足∀i∈[1,n],x≡mi(mod ai)。
输入
  第 1 行包含整数 n。
  第 2…n+1 行:每 i+1 行包含两个整数 ai 和 mi,数之间用空格隔开。
输出
  输出最小非负整数 x,如果 x 不存在,则输出 −1。
  如果存在 x,则数据保证 x 一定在 64 位整数范围内。
数据范围
  1≤ai≤231−1,
  0≤mi<ai
  1≤n≤25
输入样例:
  2
  8 7
  11 9
输出样例:
  31

中国剩余定理

结论

可以发现有个解x=M/m1*n1+M/m2*n2+M/m3*n3+...+M/mi*ni
  其中M为mi的乘积,ni是mi的逆元

代码:

#include <iostream>

using namespace std;

typedef long long LL;

const int N = 15;

int n;
int a[N], m[N];

void exgcd(LL a, LL b, LL &x, LL &y) {
    if (!b) x = 1, y = 0;
    else {
        exgcd(b, a % b, y, x);
        y -= a / b * x;
    }
}
int main() {
    cin >> n;
    LL M = 1;
    for (int i = 0; i < n; ++ i) {
        cin >> m[i] >> a[i];
        M *= m[i];  //读入mi的同时计算M
    }
    LL res = 0;
    for (int i = 0; i < n; ++ i) {
        LL Mi = M / m[i];   //计算Mi = M/mi
        LL ti, y;
        //这一步是求逆元,根据逆元公式的衍生公式可以得到 ti * Mi + y * mi = 1
        exgcd(Mi, m[i], ti, y);
        res += a[i] * Mi * ti;  //计算的同时累加到res中(上述公式里有个sum需要累加)
    }
    cout << (res % M + M) % M << endl;  //对于任意x+kM都是满足要求的解,但目标是输出最小的正整数x,因此取模即可
    return 0;
}
posted @ 2021-09-08 20:06  巴扎嘿~  阅读(85)  评论(0编辑  收藏  举报