[lnsyoj163/luoguP1495]曹冲养猪

题意

求线性同余方程组

\[\begin{cases}x\equiv b_1\pmod{a_1}\\x\equiv b_2\pmod{a_2}\\\dots\\x\equiv b_n\pmod{a_n}\end{cases} \]

的最小非负整数解,保证 \(a_1,a_2,\cdots,a_n\)互质。

sol

求解线性同余方程组,我们通常会选择中国剩余定理(CRT)来解决。
我们计算 \(A = a_1 \cdot a_2 \cdots a_n\)\(m_i = \frac{A}{a_i}\),由于 \(m_i\) 是除 \(a_i\)\(a\) 中所有数的倍数,因此 \(k\cdot m_i \equiv 0 (\bmod a_p)(p\ne i)\),即该值只对第 \(i\) 个线性同余方程有影响。因此,我们只需要解线性同余方程\(m_i \cdot x \equiv 1\pmod{a_i}\),那么\(b_ix\)就是第\(i\)个线性同余方程的贡献,贡献的和即为线性同余方程组的一组合法解,将其取模\(A\)即可求出最小合法解

代码

#include <iostream>
#include <algorithm>
#include <cstring>

using namespace std;
typedef long long LL;

const int N = 15;

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

LL exgcd(LL a, LL b, int &x, int &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(){
    cin >> n;
    for (int i = 1; i <= n; i ++ ) cin >> a[i] >> b[i];
    LL M = 1;
    for (int i = 1; i <= n; i ++ ) M *= a[i];
    LL sum = 0;
    for (int i = 1; i <= n; i ++ ) {
        int x, y;
        LL d = exgcd(M / a[i], (LL) a[i], x, y);
        int t = abs(a[i] / d);
        x /= d;
        sum += (x % t + t) % t * (M / a[i]) * b[i];
    }

    cout << sum % M << endl;

    return 0;
}
posted @ 2024-06-25 20:18  是一只小蒟蒻呀  阅读(12)  评论(0编辑  收藏  举报