问题描述
“今有物不知其数,三三数之余二,五五数之余三,七七数之余二。问物几何?”
emmm这是。。最开始这个问题被提出来的描述
其实说白了就是求解一次同余式组
然后还可以。。解决一些。。需要将模数转化成素数来求解的题目
具体内容
我们还是把这个东西写成数学语言吧,一般化一点的长这样:
\[
\begin{cases}
x\equiv a_1(mod\ m_1)\\
x\equiv a_2(mod\ m_2)\\
x\equiv a_3(mod\ m_3)\\
...\\
x\equiv a_n(mod\ m_n)\\
\end{cases}
\]
其中模数\(m_i\)两两互素,记\(N=\prod\limits_{i=1}^{n}m_i\),中国剩余定理说的是:这个同余方程组在模\(N\)意义下有唯一解,并且给出了一种具体的构造方案(也就是下面的证明)
证明:我们首先来考虑一个更加特殊一点的同余方程组
\[
\begin{cases}
x\equiv 1(mod\ m_1)\\
x\equiv 0(mod\ m_2)\\
x\equiv 0(mod\ m_3)\\
...\\
x\equiv 0(mod\ m_n)\\
\end{cases}
\]
我们可以大胆令\(x=(N/m_1)*y\),然后就会发现这个方程组就等价于求解同余方程:
\[
(N/m_1)*y \equiv1(mod\ m_1)
\]
然后对于我们改变一下左边等于\(1\)的等式是哪一条,如果是第\(i\)条的话那么就相当于求解:
\[
(N/m_i)*y_i \equiv1(mod\ m_i)
\]
那么我们令\(x_i=(N/m_i)*y_i\),就可以构造出原来的方程组(余数为\(a_i\)的那个方程组)在模\(N\)意义下的唯一解:
\[
x=\prod_{i=1}^n a_ix_i
\]
具体实现
那么现在我们只要求出\(y_i\)就好了,观察这个式子:
\[
(N/m_i)*y_i \equiv1(mod\ m_i)
\]
会发现这个\(y_i\)我们可以用扩展欧几里得求出
因为可以看成\(y_i(N/m_1)+q\cdot m_1=1\),而因为\(m_i\)是两两互素的所以\(1=gcd(N/m_1,m_1)\)
那么直接就上扩欧就好啦
代码大概长这个样子
ll ex_gcd(ll a,ll b,ll &x,ll &y){
if (b==0){x=1; y=0; return a;}
ll gcd=ex_gcd(b,a%b,x,y),tmp=x;
x=y; y=tmp-a/b*y;
return gcd;
}
ll CRT(int *w,int *a,int n){//w数组里面存的是模数,a里面存的是余数
ll x,y,ret=0,mod=1,tmp;//这里的mod就是相当于上面讲的N啦
for (int i=1;i<=n;++i) mod*=w[i];
for (int i=1;i<=n;++i){
tmp=mod/w[i];
ex_gcd(w[i],tmp,x,y);
ret=(ret+y*tmp*a[i])%mod;
}
return (ret+mod)%mod;
}
具体应用
应用的话。。其实就是像上面提到的那样,解决一些要拆模数的问题
比如说 -->这题(bzoj3782)
简单说一下就是,这题需要用到Lucas定理,但是这个定理有一个限制条件就是模数必须是质数,那么解决方法就是将模数分解质因数一下,然后分别用Lucas定理求出在几个质因数下的答案,最后用CRT(中国剩余定理)合并一下得到在模那个非质数的模数下的答案就好了
目前了解到的就主要是这样的类型的qwq
在FFT中也有应用,但是还没有去写。。所以先留着坑吧qwq
不互质呢?
其实中国剩余定理的条件还是有点苛刻的,模数之间要两两互质
如果说不能满足这一点呢?
其实也是可以做的,这里我们可以采用一个两两合并的思想
假设我们现在要合并两个方程:
\[
\begin{cases}
x\equiv a_1(mod\ m_1)\\
x\equiv a_2(mod\ m_2)
\end{cases}
\]
但是其中\(,m_1,m_2\)是不互质的
我们可以将上面那个方程组写成
\[
\begin{cases}
x=a_1+x_1\cdot m_1\\
x=a_2+x_2\cdot m_2
\end{cases}
\]
那么:
\[
x_1\cdot m_1-x_2\cdot m_2=a_2-a_1\\
\]
然后如果说这个有解的话,那么我们可以用扩展欧几里得解出\(x_1\)的最小正整数解,然后代入求得\(x=a_1+m_1*x_1\)
然后最后合并为一个方程的结果就是:
\[
x\equiv y(mod\ lcm(m_1,m_2))
\]
然后多个同余方程的话我们就两个两个一路合并下去就好了
代码的话。。还没有写qwq晚点填坑嗯qwq