中国剩余定理证明及模版

POJ 1006 Biorhythms
证明

算法证明如上。
在实际求解时,可能不满足n1,n2,n3…nk,互质,那么令N=LCM(n1,n2,…,nk)最小公倍数,即保证算法正确性。
可以发现,求解m时,与a无关,所以,题目若是固定取模的数不动,但是改变a的值,可以预处理出m,然后根据题目计算答案。正是POJ 1006 Biorhythms.
得到的x,可能是正可能负,这只是方程组的一个解,方程组的通解满足X = x + N*t , t为任意整数。

模版

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long LL;
const int MAXN = 1e5;
/*
x = a1(mod n1)
...
x = ak(mod nk)
x = a1*m1+a2*m2+...+ak*mk
N = LCM(n1, n2, ..., nk)
*/
int num; // 等式的数量
LL a[MAXN];
LL n[MAXN];
LL N; // 调整x的大小时会用到,所以放在全局里
LL LCM(LL* n, int num) {
    LL gcd = n[0];
    LL ans = 1;
    for(int i = 1; i < num; i++)
        gcd = __gcd(gcd, n[i]);
    for(int i = 0; i < num; i++)
        ans *= n[i]/gcd;
    return ans;
}
LL exgcd(LL a, LL b, LL& x, LL& y) {
    if(b == 0) {
        x = 1;
        y = 0;
        return a;
    }else {
        LL r = exgcd(b, a%b, x, y);
        LL t = y;
        y = x-a/b*y;
        x = t;
        return r;
    }
}
LL crt() {  // Chinese Remainder Theorem
    LL N = LCM(n, num);
    LL x = 0;
    for(int i = 0; i < num; i++) {
        LL u, v;
        exgcd(n[i], N/n[i], u, v);
        // mi = N/n[i]*v;
        x += N/n[i]*v*a[i];
    }
    return x;
}
int main() {
    scanf("%d", &num);
    for(int i = 0; i < num; i++) {
        scanf("%lld%lld", &a[i], &n[i]);
    }
    LL x = crt(); // 计算等式一个解


    cout << x << endl;
    return 0;
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值