首页 > 其他分享 >CRT&EXCRT(中国剩余定理和扩展中国剩余定理)

CRT&EXCRT(中国剩余定理和扩展中国剩余定理)

时间:2023-01-29 19:34:05浏览次数:60  
标签:剩余 begin CRT pmod 定理 mid times cases equiv

稍微难一点,其实也挺简单。

CRT:

用途:

给定一个同余方程组,保证所有 \(m\) 两两互质:

\[\begin{cases} x\equiv a_1\pmod{m_1} \\ x\equiv a_2\pmod{m_2} \\ ... \\ x\equiv a_n\pmod{m_n}\end{cases} \]

用于求其解。

具体方法:

自我感觉叫方法好一点,建议理解记忆,公式见下。
首先我们先找一组数 \(n\) ,使得:

\[n_i \bmod m_i = a_i \text{ 或者说 }n_i\equiv a_i\pmod{m_i} \]

因为:如果 \(a \bmod b = t\) 那么 \((a+k\times b) \bmod b = t\) (比较显然
所以:
如果 \(m_1 \mid n_2\) 那么 \((n_1 + n_2) \bmod m_1 = a_1\)
如果 \(m_2 \mid n_1\) 那么 \((n_1 + n_2) \bmod m_2 = a_2\)
也就是说,要想使

\[\begin{cases} n_1 + n_2\equiv a_1\pmod{m_1} \\ n_1 + n_2\equiv a_2\pmod{m_2}\end{cases} \]

只需要

\[\begin{cases} m_1 \mid n_2 \\ m_2 \mid n_1 \end{cases} \]

同理,我们设 \(sum=\sum\limits_{i=1}^nn_i,M=\prod\limits_{i=1}^nm_i\) 要想使:

\[\begin{cases} sum\equiv a_1\pmod{m_1} \\ sum\equiv a_2\pmod{m_2} \\ ... \\ sum\equiv a_n\pmod{m_n}\end{cases} \]

只需要

\[\begin{cases} n_1 \mid m_2,m_3,...,m_n\\ n_2 \mid m_1,m_3,...,m_n \\ ... \\ n_n \mid m_1,m_2,...,m_{n-1}\end{cases} \]

因为所有 \(m\) 两两互质,所以只需要

\[n_i \mid M \div m_i \]

接下来考虑怎么求 \(n_i\)
我们设 \(n_i=M\div m_i \times t_i\)
于是我们只需求一个 \(t_i\) ,使其满足

\[M\div m_i \times t \equiv a_i\pmod{m_i} \]

因为 \(M\div m_i\) 是个常数,所以直接用 \(exgcd\)求解即可。
当然也可以先用乘法逆元算 \(M\div m_i \times t \equiv 1\pmod{m_i}\) 在乘上 \(a_i\) ,本质相同。

这样我们就可以求出所有 \(n_i\) ,进而求出 \(x=\sum\limits_{i=1}^nn_i\),如果 \(x\) 要求最小,只需要 \(\bmod M\) 即可。

公式:

设 \(M=\prod\limits_{i=1}^nm_i,M_i=M \div m_i\)

\[x=\sum\limits_{i=1}^n a_i \times M_i \times M_i^{-1} \bmod M \]

例题

CODE(点击查看)
#include<bits/stdc++.h>
using namespace std;
#define llt long long
int n,m[12],a[12];

template<typename T>
inline void read(T &x){
    char s=getchar();x=0;bool pd=false;
    while(s<'0'||'9'<s){if(s=='-') pd=true;s=getchar();}
    while('0'<=s&&s<='9')x=(x<<1)+(x<<3)+(s^48),s=getchar();
    if(pd) x=-x;
}
void exgcd(llt a,llt b,llt &x,llt &y){
	if(b==0) x=1,y=0;
	else exgcd(b,a%b,y,x),y-=a/b*x;
}

int main(){
	read(n);
	long long tm=1,ans=0;
	for(int i=1;i<=n;i++) read(m[i]),read(a[i]),tm*=m[i];
	for(int i=1;i<=n;i++){
		long long lm=tm/m[i],x,y;
		exgcd(lm,m[i],x,y);
		x=(x%m[i]+m[i])%m[i];
		ans=(ans+x*a[i]*lm)%tm;
	}
	printf("%lld",ans%tm);
}

这里推荐一篇博客,讲的很细(我从那里学的,本文也有很多借鉴。

EXCRT

其实和 \(crt\) 没有什么关联,单纯推式子。
我们来看一下同余方程组

\[\begin{cases} x\equiv a_1\pmod{m_1} \\ x\equiv a_2\pmod{m_2} \\ ... \\ x\equiv a_n\pmod{m_n}\end{cases} \]

这里不保证 \(m\) 互质
首先看第一二个式子:

\[\begin{cases} x\equiv a_1\pmod{m_1} \\ x\equiv a_2\pmod{m_2}\end{cases} \]

变形得到:

\[\begin{cases} x = a_1 + m_1k_1 \\ x = a_2 + m_2k_2\end{cases} \]

\[\therefore a_1+m_1k_1=a_2+m_2k_2 \]

整理:

\[m_1k_1-m_2k_2=a_2-a_1 \]

运用 \(exgcd\) 解得 \(k_1\) 的一组解:

\[k_1=r \]

\[\therefore k_1 \text{ 的通解为 } k_1=r+\frac{m_2}{\gcd(m_1,m_2)} \times t \mid t \in Z \]

将上式带入 \(x = a_1 + m_1k_1\) 得:

\[x=a_1+m_1r+\frac{m_1m_2}{\gcd(m_1,m_2)}\times t \]

\[\because \operatorname{lcm(m_1,m_2)}=\frac{m_1m_2}{\gcd(m_1,m_2)} \]

\[\therefore x=a_1+m_1r+\operatorname{lcm(m_1,m_2)}\times t \]

变形得到:

\[x\equiv a_1+m_1r\pmod{\operatorname{lcm(m_1,m_2)}} \]

于是我们就成功将两个同余方程化简成了一个。
同理化简下去直到一个,求解即可。

例题

CODE(点击查看)
#include<bits/stdc++.h>
using namespace std;
#define llt long long
__int128 n,na=0,nm=1;

template<typename T>
inline void read(T &x){
    char s=getchar();x=0;bool pd=false;
    while(s<'0'||'9'<s){if(s=='-') pd=true;s=getchar();}
    while('0'<=s&&s<='9')x=(x<<1)+(x<<3)+(s^48),s=getchar();
    if(pd) x=-x;
}
llt gcd(llt a,llt b){return (b==0)?a:gcd(b,a%b);}
llt lcm(llt a,llt b){return a/gcd(a,b)*b;}
void exgcd(__int128 a,__int128 b,__int128 &x,__int128 &y){
	if(b==0) x=1,y=0;
	else exgcd(b,a%b,y,x),y-=a/b*x;
}
inline void hebing(llt a,llt m){
	llt sa=a-na;
	__int128 x,y;
	llt gd=gcd(nm,m);
	exgcd(nm,m,x,y);
	llt lm=m/gd;x*=(sa/gd),y*=(sa/gd);
	x=(x%lm+lm)%lm;
	na=na+nm*x;
	nm=lcm(nm,m);
}

int main(){
#ifndef ONLINE_JUDGE
    freopen("in.in","r",stdin);
    freopen("out.out","w",stdout);
#endif
	read(n);
	for(llt a,m,i=1;i<=n;i++) read(m),read(a),hebing(a,m);
	__int128 x,y;
	exgcd(1,nm,x,y);
	x=(x*na%nm+nm)%nm;
	long long ans=x; 
	printf("%lld",ans);
}

参考博客:https://www.cnblogs.com/sparkyen/p/11432052.html

标签:剩余,begin,CRT,pmod,定理,mid,times,cases,equiv
From: https://www.cnblogs.com/xrlong/p/17073430.html

相关文章

  • 中国剩余定理
    中国剩余定理先看一道\(poj\)上的题目:【\(POJ1006\)】\(Biorhythms\)题意:人自出生起就有体力,情感和智力三个生理周期,分别为\(23\),\(28\)和\(33\)天。一个周期内有......
  • Lucas 定理
    简述当问题规模很大,而模数是一个不大的质数的时候,就不能简单地通过递推求解来得到答案,需要用到Lucas定理。LucasLucas定理内容如下:对于质数\(p\),有\[\binom{n}{m}......
  • 矩阵树定理
    简述Kirchhoff矩阵树定理(简称矩阵树定理)解决了一张图的生成树个数计数问题。主要步骤无向图假设现在给定一个无向图\(G\)定义度数矩阵\(D\):若存在边\((u,v,w)\),则\(D......
  • 【学习笔记】Burnside引理与Polya定理(无证)
    群论笔记Burnside引理\[置换后本质不同的数量=\frac{1}{置换方式总数}\times所有置换后与原来相同的构造方案\]注意:单位元也是置换Polya定理举例说明。考虑立方体......
  • 背驰转折定理
     缠中说禅-背驰转折定理:某级别趋势背驰将导致1、最后一个中枢级别扩展2、该级别更大中枢的盘整3、反趋势 出第三买卖点延续原有走势出现3卖整体级别变大......
  • 中值定理
    模型:如果一个序列\(a\)长度为\(p\),\(a_1=0,a_p=1\),需要找到一个长度为\(q\)的子序列\(a[l,r]\)使得\(a_l=0,a_r=1\),且\(q|p\),那么可以这样考虑:对于\(......
  • 线性空间的基本概念与定理1
    线性空间的基本概念与定理1.线性空间:给定集合$V$与数域$\mathbb{K}$,在$V$上定义加法运算$"+"$,以及数域$\mathbb{K}$与集合$V$之间的数乘运算,并要求上述加法运算满足交换......
  • 采样定理与SDMDM
    1.信噪比=6.02N+1.76dB对于这个经常引用的AD/DA转换器理论信噪比(SNR)公式,代表一个完美的N位ADC的理论性能。下面先计算N位模数转换器(ADC)的理论量化噪声。一旦通过计算均方根......
  • 2023.1.16[模板] 二次剩余
    2023.1.16二次剩余问题叙述给出N,p,求解方程$x^2\equivN$(\(modp\))且保证p是奇素数。算法流程解的数量首先,探究$x^2\equivN$这个方程解的数量,假设我们......
  • 算法学习笔记(9): 中国剩余定理(CRT)以及其扩展(EXCRT)
    扩展中国剩余定理讲解扩展之前,我们先叙述一下普通的中国剩余定理中国剩余定理中国剩余定理通过一种非常精巧的构造求出了一个可行解但是毕竟是构造,所以相对较复杂\[......