中国剩余定理 (韩信点兵定理)

#

给出一系列线性同余方程:
x≡a[1](mod m[1])
x≡a[2](mod m[2])
x≡a[3](mod m[3])

求x的最小值

令M=m[1]∗m[2]∗…∗m[n]
令M[i]=M/m[i], 因为m[]中的数两两互质,所以M[i]与m[i]互质,所以可以用扩欧求出M[i]的逆元
t[i]是M[i]在模m[i]下的逆元,即M[i]∗t[i]≡1(mod m[i])
x=∑a[i]M[i]t[i] 余数分乘积逆元

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 @   liang302  阅读(442)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
点击右上角即可分享
微信分享提示
主题色彩