[lnsyoj517/luoguP4777]扩展中国剩余定理

题意

原题链接
求线性同余方程组

{xb1(moda1)xb2(moda2)xbn(modan)

的最小非负整数解。

sol

[lnsyoj163/luoguP1495]曹冲养猪不同的是,本题无法保证互质,这就导致中国剩余定理无法使用,需要一种新的方式来解决问题。
我们思考:如果我们可以将两个方程合并为一个方程,那么整个方程组都可以合成为一个方程,问题也就解决。
下面进行推导:
对于两个方程 xb1(moda1)xb2(moda2),,我们将其分别转换为 x+a1p=b1x+a2q=b2,整理得 a2qa1p=b2b1,利用扩展欧几里得算法,我们可以求出一组可行解 p,q。此时,新的方程的 b 即为原来的 b+a1p,新的方程的 a 即为原来的 a1,a2 的最大公倍数。
最终,合并成的一个方程,其 b 的值即为最终答案.
注意:勤取模

代码

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

using namespace std;
typedef long long LL;

const int N = 100005;

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

LL exgcd(LL a, LL b, __int128 &x, __int128 &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(){
    while (scanf("%d", &n) != EOF){
        for (int i = 1; i <= n; i ++ ) scanf("%lld%lld", &m[i], &a[i]);
        LL b = a[1];
        __int128 M = m[1];
        bool flag = false;
        for (int i = 2; i <= n; i ++ ){
            __int128 p, q;
            LL d = exgcd(M, m[i], p, q);
            if (((a[i] - b % m[i] + m[i]) % m[i]) % d) {
                flag = true;
                puts("-1");
                break;
            }
            __int128 u = 1;
            p = u * p * ((a[i] - b % m[i] + m[i]) % m[i]) / d;
            LL t = abs(m[i] / d);
            p = (p % t + t) % t;
            LL m1 = M;
            M = M / d * m[i];
            b = ((u * m1 * p % M + b % M) % M + M) % M;
        }
        if (flag) continue;
        printf("%lld\n", b);
    }
    return 0;
}
posted @   是一只小蒟蒻呀  阅读(14)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示