中国剩余定理(CRT)

Published on7/29/2025
Created on 12/17/2021

中国剩余定理用于求解如下形式的一元线性同余方程组:

{xa1(mod m1)xa2(mod m2)xa3(mod m3)xan(mod mn)\begin{cases} x&\equiv a_1&(\mathrm{mod}\ m_1)\\ x&\equiv a_2&(\mathrm{mod}\ m_2)\\ x&\equiv a_3&(\mathrm{mod}\ m_3)\\ &\vdots\\ x&\equiv a_n&(\mathrm{mod}\ m_n)\\ \end{cases}

普通算法只适用于模数 m1,m2,,mnm_1,m_2,\dots,m_n 两两互质的情况。 先上算法:

证明: 对于所有 m1,m2,m3,,mnm_1',m_2',m_3',\dots,m_n' 中的其中一个 mim_i' ,其就为剔除了 mim_iMM,除其之外其他 mm' 均有一因子 mim_i 。即:

ji, mj0(mod mi)\forall j\neq i,\ m_j'\equiv 0\quad(\mathrm{mod}\ m_i)

所以,我们算出的答案满足,对于任意一条方程 xai(mod mi)x\equiv a_i\quad(\mathrm{mod}\ m_i)

xj=1najcj(mod ni)a1m1m11++aici++anmnmn1(mod ni)0+0++aici++0+0(mod ni)aimimi1(mod ni)(mod ni)ai(mod ni)\begin{aligned} x&\equiv\sum^n_{j=1}a_jc_j&(\mathrm{mod}\ n_i)\\ &\equiv a_1m_1'm_1'^{-1}+\dots+a_ic_i+\dots+a_nm_n'm_n'^{-1} &(\mathrm{mod}\ n_i)\\ &\equiv 0+0+\dots+a_ic_i+\dots+0+0 &(\mathrm{mod}\ n_i)\\ &\equiv a_im_i' \underset{(\mathrm{mod}\ n_i)}{m_i'^{-1}} &(\mathrm{mod}\ n_i)\\ &\equiv a_i&(\mathrm{mod}\ n_i) \end{aligned}

参考代码

题目:P1495 【模板】中国剩余定理(CRT)/曹冲养猪 - 洛谷)

#include <cctype>
#include <cstdio>
#include <cstring>
#include <iostream>
//---//
#include <algorithm>
#include <cmath>
#include <vector>
using namespace std;

typedef unsigned int u;
typedef long long ll;
typedef unsigned long long llu;

#define rep(i, a, b) for (ll i = a; i < b; i++)
#define REP(i, a, b) for (ll i = a; i <= b; i++)
#define per(i, b, a) for (ll i = b; i >= a; i--)

const ll N = 11;

ll a[N], m[N];

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

signed main() {
  ll n, M = 1, x, y, c, ans = 0;
  scanf("%lld", &n);
  REP(i, 1, n) {
    scanf("%lld%lld", &m[i], &a[i]);
    M *= m[i];
  }
  REP(i, 1, n) {
    c = M / m[i];
    exgcd(c, m[i], x, y);
    c *= (x % m[i] + m[i]) % m[i];
    ans = (ans + a[i] * c % M) % M;
  }
  printf("%lld", ans);
}

// https://www.luogu.com.cn/record/61038480