中国剩余定理

中国剩余定理

前置知识

逆元(扩展欧几里得算法,费马小定理),模意义下的四则运算

介绍

中国剩余定理主要用于解决这样的线性同余方程组,其中 \(b_1,b_2,\cdots,b_n\) 两两互质

\[\left\{ \begin{aligned} x&\equiv a_1\pmod {b_1}\\ x&\equiv a_2\pmod {b_2}\\ &\ \ \vdots\\ x&\equiv a_n\pmod {b_n}\\ \end{aligned} \right. \]

对于这样的方程组我们只需要求出 \(x\) 的一组特解,把这个特解加上 \(b_1,b_2,\cdots,b_n\) 的最小公倍数的任意整数倍就可以得到所有解,所以我们就只需要考虑怎么构造出一组特解

例子

下面举个例子来帮助理解

\[\left\{ \begin{aligned} x&\equiv 2\pmod 3\\ x&\equiv 4\pmod 7\\ x&\equiv 5\pmod 8\\ \end{aligned} \right. \]

直接构造不太行,但是对于每一个线性同余方程构造出一个特解是非常轻松的,所以我们先设第 \(i\) 个式子的解是 \(y_i\),那么有

\[\left\{ \begin{aligned} y_1&\equiv 2\pmod 3\\ y_2&\equiv 4\pmod 7\\ y_n&\equiv 5\pmod 8\\ \end{aligned} \right. \]

最终的 \(x\) 一定是 \(y_i\) 以各种方式组合起来,那么问题就是怎么组合才能得到 \(x\),如果 \(y_i\) 之间相乘就把问题变得更复杂了,所以我们把它们加起来,想办法凑出 \(x\)

如果 \(x=y_1+y_2+y_3\),那么每一个 \(y\) 需要满足什么条件呢?

因为 \(y_1+y_2+y_3\equiv y_1\equiv 2\pmod 3\),所以 \(y_2+y_3\) 一定是 \(3\) 的倍数,当 \(y_2,y_3\) 分别都是 \(3\) 的倍数时这一定也是满足条件的一个特解

所以我们不妨假设 \(y_2,y_3\) 都是 \(3\) 的倍数

同理 \(y_1,y_3\) 都是 \(7\) 的倍数,\(y_1,y_2\) 都是 \(8\) 的倍数

那我们就可以把 \(y_1\) 写成 \(56z_1\),把 \(y_2\) 写成 \(24z_2\),把 \(y_3\) 写成 \(21z_3\)

原方程就变成了这样

\[\left\{ \begin{aligned} 56z_1&\equiv 2\pmod 3\\ 24z_2&\equiv 4\pmod 7\\ 21z_3&\equiv 5\pmod 8\\ \end{aligned} \right. \]

然后就非常好求了,只需要求出

\[\left\{ \begin{aligned} 56w_1&\equiv 1\pmod 3\\ 24w_2&\equiv 1\pmod 7\\ 21w_3&\equiv 1\pmod 8\\ \end{aligned} \right. \]

也就是 \(21,24,56\) 分别对于 \(3,7,8\) 的乘法逆元,然后在等式两边同时分别乘以 \(2,4,5\) 就可以得到 \(z_1,z_2,z_3\) 的一组特解

用扩展欧几里得算法求出 \(w_1=2,w_2=5,w_3=5\),所以 \(z_1=2w_1=4,z_2=4w_2=20,z_3=5w_3=25\)

于是 \(y_1=56z_1=224,y_2=24z_2=480,y_3=21z_3=525\)

最后就得到 \(x=y_1+y_2+y_3=1229\),由于 \(3,7,8\) 的最小公倍数是 \(168\),我们将 \(1229\) 对于 \(168\) 取模就能得到 \(x\) 的最小正整数解 \(53\)

\(x\) 的通解就能表示为 \(53+168k,k\in\mathbb{Z}\)

数学语言

上面的例子比较好理解,下面用更严谨的数学语言再来描述一遍,没兴趣可以直接跳过

直接构造不太行,但是对于每一个线性同余方程构造出一个特解是非常轻松的,所以我们先设第 \(i\) 个式子的解是 \(y_i\),那么有

\[\left\{ \begin{aligned} y_1&\equiv a_1\pmod {b_1}\\ y_2&\equiv a_2\pmod {b_2}\\ &\ \ \vdots\\ y_n&\equiv a_n\pmod {b_n}\\ \end{aligned} \right. \]

最终的 \(x\) 一定是 \(y_i\) 以各种方式组合起来,如果 \(y_i\) 之间相乘就把问题变得更复杂了,所以我们把它们加起来以凑出 \(x\)

如果 \(x=\sum_{i=1}^ny_i\),那么考虑每一个 \(y\) 需要满足的条件

由于 \(y_t\equiv a_t\pmod {b_t}\)\(x=\sum_{i=1}^ny_i\equiv a_t\pmod {b_t}\),所以 \(y_t\equiv\sum_{i=1}^ny_i\pmod {b_t}\)

因为只要构造一组特解所以我们不妨假设 \(\sum_{i=1}^ny_i[i\ne t]\equiv 0\pmod {b_t}\),也就是 \(b|\sum_{i=1}^ny_i[i\ne t]\)

用人话说就是 \(y_t\) 在加上所有其他 \(y\) 之后对于 \(b_t\) 取模的结果仍然不变,所以其他所有 \(y\) 的和一定是 \(b_t\) 的倍数,因为只要构造一组特解所以我们不妨假设其他每一个 \(y\) 都是 \(b_t\) 的倍数

不妨令 \(p_t=\prod_{i=1}^nb_i[i\ne t]\)\(y_t=p_tz_t\)

原方程组就转换为了

\[\left\{ \begin{aligned} p_1z_1&\equiv a_1\pmod {b_1}\\ p_2z_2&\equiv a_2\pmod {b_2}\\ &\ \ \vdots\\ p_nz_n&\equiv a_n\pmod {b_n}\\ \end{aligned} \right. \]

假设 \(p_t\) 在模 \(b_t\) 意义下的乘法逆元为 \(w_t\),那么根据乘法逆元的定义 \(p_tw_t\equiv1\pmod {b_t}\),两边同时乘以 \(a_t\) 就有 \(p_ta_tw_t\equiv a_t\pmod {b_t}\),所以 \(a_tw_t\) 一定是 \(z_t\) 的一个特解

那么对于 \(p_tz_t\equiv a_t\pmod {b_t}\)\(z_t\) 一定有一个特解为 \(p_t\) 在模 \(b_t\) 意义下的乘法逆元的 \(a_t\)

\(p\) 可以直接算出来,然后利用扩展欧几里得算法(\(b\) 为质数时也可以使用费马小定理)求出 \(w\),乘上 \(a\) 就能得到 \(z\),再将 \(z\) 乘上 \(p\) 就能得到 \(y\),全部加起来就可以算出 \(x\) 的一个特解了,只需要模 \(b_1,b_2,\cdots,b_n\) 的最小公倍数就可以得到最小正解

C++ Code

模板题目传送门 Luogu P1495

#include<bits/stdc++.h>
#define in read()
using namespace std;
typedef long long ll;
inline int read()
{
    char c=getchar();
    int x=0;
    while(c<48)c=getchar();
    while(c>47)x=(x*10)+(c^48),c=getchar();
    return x;
}
inline void mwrite(ll a)
{
    if(a>9)mwrite(a/10);
    putchar((a%10)|48);
}
inline void write(ll a,char c)
{
	mwrite(a);
	putchar(c);
}
//上面是IO优化 
const int MAXN=15;
int n,c[MAXN],d[MAXN];
inline void exgcd(ll a,ll b,ll &x,ll &y)//扩展欧几里得 
{
    if(!b) return x=1,y=0,void(0);
    exgcd(b,a%b,y,x);
    y-=(a/b)*x;
}
inline ll inv(ll x,ll p)//求逆元 
{
	ll X,Y;
	exgcd(x,p,X,Y);
	return (X%p+p)%p;
}
inline ll crt()//CRT
{
	ll prod=1,ans=0;
	for(int i=1;i<=n;++i) prod*=d[i];
	ll tmp;
	for(int i=1;i<=n;++i)
	{
		tmp=prod/d[i];
		ans+=(inv(tmp,d[i])*c[i]*tmp)%prod;
	}
	return ans%prod;
} 
signed main()
{
	n=in;
	for(int i=1;i<=n;++i) d[i]=in,c[i]=in;
	write(crt(),'\n');
    return 0;
}

博客园传送门

知乎传送门

posted @ 2022-08-10 14:13  人形魔芋  阅读(136)  评论(0编辑  收藏  举报