中国剩余定理(推导)

/* 
    中国剩余定理(孙子定理)
    没想到又要学这玩意, 但是二刷还算轻松
    这是用来解出一堆线性同余方程组同一解的定理
    常见是这样的(求解x)
    x ≡ a1 (mod m1)
    x ≡ a2 (mod m2)
    x ≡ a3 (mod m3)
    ... 
    x ≡ an (mod mn)
    
    其中任意两个mi互质
    
    M = m1 * m2 * m3 * ... * mn
  	Mi = M / mi
    ti是Mi关于mi的逆元, 即Mi * ti ≡ 1 (mod mi)
    
    那么x = Σ ai * Mi * ti (1 <= i <= n)
    中国剩余定理是通过构造来得到一组解, 因此只需要证明可行即可
    你可以尝试带入进去
    比如这里带入第一个式子x ≡ a1 (mod m1)
    因为x中除了第1项, 其他所有的ai * Mi * ti中的Mi里面都有m1这个因子, 那么其他项就可以被%m1完美消掉
    只剩下第一项即, a1 * M1 * t1, 又因为Mi * ti ≡ 1 (mod mi), 那么M1 * t1 在%m1下就为1
    那么就只剩下a1, 符合等式1, 
    对于其他的等式同理, 这就说明, 这是一个正确解
    
    关于ti一定有解, Mi * ti ≡ 1 (mod mi), 因为Mi = M / mi, mi和其他mi互质, 因此(Mi, mi) = 1
    通过裴蜀定理可得式子Mi*x + mi*y = 1, 而Mi * ti ≡ 1 (mod mi), 可以化成等式Mi * ti + mi*y = 1
    那么Mi*x + mi*y = 1中的x就是ti, Mi*x + mi*y = 1存在, Mi * ti + mi*y = 1一定存在
    x一定有解, 即ti一定有解, 那么ti就一定可以通过exgcd求出
    
    值得一提的是M是所有mi的乘积, 那么通解应该也就知道了, 即x = x0 + k*M
    我x加上k个M不影响每个mi取余它还是ai, 也就都是解, 
    (这里有多组解的原因也是, 有n个式子但能找出来n + 1个未知数(把同余方程列乘等式), 因此有无数解)
    
    所以最小正整数解就是(x % M + M) % M
*/

AcWing 1298. 曹冲养猪 - AcWing

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

using namespace std;

typedef long long LL;

const int N = 11;

int n, m;
int A[N], B[N];
LL M = 1;

void exgcd(LL a, LL b, LL &x, LL &y)
{
    if (b == 0)
    {
        x = 1;
        y = 0;
        return ;
    }
    exgcd(b, a % b, y, x);
    y -= a / b * x;
}

int main()
{
    cin >> n;
    for (int i = 1; i <= n; i ++ )
    {
        cin >> A[i] >> B[i];
        M *= A[i]; 
    }
    LL res = 0;
    for (int i = 1; i <= n; i ++ )
    {
        LL Mi = M / A[i];
        LL ti, x;
        exgcd(Mi, A[i], ti, x);
        res += ti * B[i] * Mi;
    }
    cout << (res % M + M) % M << endl;
    return 0;
}

贴一个学习网站,课挺便宜的,可以试试
starrycoding

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值