中国剩余定理(CRT)及其拓展(ExCRT)
中国剩余定理 CRT
推导
给定\(n\)个同余方程
\[\left\{
\begin{aligned}
x &\equiv a_1 \pmod{m_1} \\
x &\equiv a_2 \pmod{m_2} \\
&... \\
x &\equiv a_n \pmod{m_n}
\end{aligned}
\right.
\]\(m_1, m_2 , ... , m_n\)两两互质
令\(M = \prod_{i=1}^{n} m_i\),求\(x \mod M\)
解决该问题的方法是构造。
我们假定最终答案的形式是一个\(n\)个项的和式,对每个同余方程的构造反应在对应项的系数上。
如果要对每一个项分别构造,就要求为每一项乘上一个合适的数,使得每项构造的系数对其他方程的结果没有影响。
容易想到构造
\]
显然该数仅在模\(m_i\)时不为\(0\),于是改变该项的系数将不会对其他方程造成影响。
现在我们希望该项模\(m_i\)意义下是\(a_i\),但上一次的构造残留下了一个\(M_i\)。简单粗暴的乘上\(M_i\)在模\(m_i\)意义下的逆元\(inv_{m_i}(M_i)\),让该项在模\(m_i\)意义下变为\(1\),然后乘上\(a_i\)就构造出来了。
综上,答案为
\]
模数互质条件保证了\(M_i\)非\(0\),保证了\(inv_{m_i}(M_i)\)的存在。
实现
大部分题的所有\(m_i\)都是质数,求逆元\(QPow\)即可。
对于一般的情况,上exgcd就行。
板题:洛谷P1495 曹冲养猪
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<ctime>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<vector>
#include<map>
#include<set>
using namespace std;
typedef long long ll;
namespace ExGcd{
ll x,y;
ll ExGcd(ll a,ll b){
ll ans;
if(a%b==0){
x=0;y=1;ans=b;
}else{
ans=ExGcd(b,a%b);
ll x1=x,y1=y;
x=y1;y=x1-a/b*y1;
}
return ans;
}
bool SolveEqu(ll a,ll b,ll c){
ll d=ExGcd(a,b);
if(c%d!=0) return 0;
x*=c/d;y*=c/d;
x=(x%b+b)%b;
y=(c-a*x)/b;
return 1;
}
}
ll Inv(ll a,ll m){
ExGcd::SolveEqu(a,m,1);
return ExGcd::x;
}
const ll CRTN=20;
namespace CRT{
ll N;
ll m[CRTN],a[CRTN];
ll Sol(){
ll ans=0,M=1;
for(ll i=1;i<=N;i++) M*=m[i];
for(ll i=1;i<=N;i++){
ll Mi=M/m[i];
ans=(ans+Mi*Inv(Mi,m[i])*a[i])%M;
}
return ans;
}
}
int main(){
using namespace CRT;
scanf("%lld",&N);
for(ll i=1;i<=N;i++)
scanf("%lld%lld",&m[i],&a[i]);
printf("%lld",Sol());
return 0;
}
拓展中国剩余定理 ExCRT
ExCRT和CRT并没有什么关系,正如ExLucas和Lucas也没什么关系
其实从纯推理的角度来看,ExCRT可能还要好想一点(
推导
问题同CRT,但是模数是任意的,并不要求互质。
这时,我们就不能保证存在逆元了。那么如何解决该问题呢?
考虑如何合并两个方程。如果我们找到了合并的方法,就能如法炮制将\(n\)个方程依次合并起来,得到答案。
\begin{aligned}
x &\equiv a_1 \pmod{m_1} \\
x &\equiv a_2 \pmod{m_2}
\end{aligned}
\right.
\]
去掉同余,化为不定方程
\begin{aligned}
x &= m_1 y_1 + a_1 \\
x &= m_2 y_2 + a_2
\end{aligned}
\right.
\]
于是得到
\]
只要找到一组满足该式的\(y_1\)和\(y_2\),就能反算出\(x\),实现合并。
而我们得到的是一个二元一次的不定方程,可以用exgcd求解。
化为标准式
\]
解就是了。如果没有解,说明同余方程组无解。
于是最后化得的合并式为
\]
实现
唯一需要注意的地方是,本来解方程应该解\((m_1,-m_2,a_2-a_1)\),但ExGCD不好处理负数,所以把\(m_2\)改成了\(m_1\)。因为我们并不需要用到\(y_2\),所以显然是没有影响的。
板题:poj2891 Strange Way to Express Integers or 洛谷P4777 扩展中国剩余定理(EXCRT)
会被卡乘法爆ll,懒得改
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<ctime>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<vector>
#include<map>
#include<set>
using namespace std;
typedef long long ll;
namespace ExGcd{
ll x,y;
ll ExGcd(ll a,ll b){
ll ans;
if(a%b==0){
x=0;y=1;ans=b;
}else{
ans=ExGcd(b,a%b);
ll x1=x,y1=y;
x=y1;y=x1-a/b*y1;
}
return ans;
}
bool SolveEqu(ll a,ll b,ll c){
ll d=ExGcd(a,b);
if(c%d!=0) return 0;
x*=c/d;y*=c/d;
x=(x%b+b)%b;
y=(c-a*x)/b;
return 1;
}
}
ll Gcd(ll a,ll b){
if(a%b==0) return b;
return Gcd(b,a%b);
}
namespace ExCRT{
ll a1,m1;
void Init(){
a1=0;m1=1;
}
void Expand(ll a2,ll m2){
ExGcd::SolveEqu(m1,m2,a2-a1);
ll y1=ExGcd::x;
ll mn=m1*m2/Gcd(m1,m2);
a1=(m1*y1+a1)%mn;
m1=mn;
}
}
int main(){
ll N;scanf("%lld",&N);
ExCRT::Init();
for(ll i=1;i<=N;i++){
ll a,m;scanf("%lld%lld",&m,&a);
ExCRT::Expand(a,m);
}
printf("%lld",ExCRT::a1);
return 0;
}
2019/12/21
中国剩余定理(CRT)及其拓展(ExCRT)的更多相关文章
- 中国剩余定理(CRT)及其扩展(EXCRT)详解
问题背景 孙子定理是中国古代求解一次同余式方程组的方法.是数论中一个重要定理.又称中国余数定理.一元线性同余方程组问题最早可见于中国南北朝时期(公元5世纪)的数学著作<孙子算经>卷下第 ...
- 中国剩余定理(CRT) & 扩展中国剩余定理(ExCRT)总结
中国剩余定理(CRT) & 扩展中国剩余定理(ExCRT)总结 标签:数学方法--数论 阅读体验:https://zybuluo.com/Junlier/note/1300035 前置浅讲 前 ...
- 中国剩余定理 CRT
中国剩余定理 CRT 正常版本CRT 要解的是一个很容易的东西 \[ \begin{aligned} x\equiv a_1(mod\ m_1)\\ x\equiv a_2(mod\ m_2)\\ . ...
- 扩展GCD 中国剩余定理(CRT) 乘法逆元模版
extend_gcd: 已知 a,b (a>=0,b>=0) 求一组解 (x,y) 使得 (x,y)满足 gcd(a,b) = ax+by 以下代码中d = gcd(a,b).顺便求出gc ...
- 学习笔记:中国剩余定理(CRT)
引入 常想起在空间里见过的一些智力题,这个题你见过吗: 一堆苹果,\(3\)个\(3\)个地取剩\(1\)个,\(5\)个\(5\)个地取剩\(1\)个,\(7\)个\(7\)个地取剩\(2\)个,苹 ...
- 拓展中国剩余定理(exCRT)摘要
清除一个误区 虽然中国剩余定理和拓展中国剩余定理只差两个字,但他俩的解法相差十万八千里,所以会不会CRT无所谓 用途 求类似$$\begin{cases}x \equiv b_{1}\pmod{a_{ ...
- 欧几里得(辗转相除gcd)、扩欧(exgcd)、中国剩余定理(crt)、扩展中国剩余定理(excrt)简要介绍
1.欧几里得算法(辗转相除法) 直接上gcd和lcm代码. int gcd(int x,int y){ ?x:gcd(y,x%y); } int lcm(int x,int y){ return x* ...
- 中国剩余定理及其拓展 CRT&EXGCD
中国剩余定理,又叫孙子定理. 作为一个梗广为流传.其实它的学名叫中国单身狗定理. 中国剩余定理 中国剩余定理是来干什么用的呢? 其实就是用来解同余方程组的.那么什么又是同余方程组呢. 顾名思义就是n个 ...
- CRT&EXCRT 中国剩余定理及其扩展
前言: 中国剩余定理又名孙子定理.因孙子二字歧义,常以段子形式广泛流传. 中国剩余定理并不是很好理解,我也理解了很多次. CRT 中国剩余定理 中国剩余定理,就是一个解同余方程组的算法. 求满足n个条 ...
随机推荐
- centos 生成网卡UUID
在Linux或CentOS中,可以通过如下命令获取网卡的uuid信息: uuidgen 网卡名07d07031-eb0f-4691-8606-befb46645433 查看网卡UUID nmcli c ...
- 树莓派4B安装netcore
准备材料 SDFormatter.exe ---格式化SD卡,空的SD就可以不用了 2019-09-26-raspbian-buster.img ---下载好树莓派系统镜像 win32diskimag ...
- Linux 命令记录
记录Linux下使用过的命令: Linux端 1.测试当前系统支持语言(我这用的是xshell,如果出现乱码,则在file-properties-terminal-encoding中,设置为utf-8 ...
- python3 之 判断闰年小实例
一.方法1: while True: try: year = int(input('请输入一个年份:')) if (year % 4) == 0 and (year % 100) != 0 or (y ...
- Spring中常见的设计模式——原型模式
1.原型模式应用场景 当遇到大量耗费劳动力的 get,set赋值场景时,如下: public class SetGetParam { public void setParam(UserDto user ...
- java中大整型BigInteger及setBit和testBit方法
最近在修改公司之前的项目,在项目中遇到了权限校验的问题,代码中出现了BigInteger的setBit()testBit()方法,之前未接触过,所以了解了下BigInteger. 在Java中,由CP ...
- MySql 表索引设计原则
索引的优点 1.加快数据的检索速度,这是创建索引的最主要的原因; 2.通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性; 3.加速表和表之间的连接; 4.在使用分组和排序子句进行数据检索时,可 ...
- Stack Overflow 上 370万浏览量的一个问题:如何比较 Java 的字符串?
在逛 Stack Overflow 的时候,发现了一些访问量像喜马拉雅山一样高的问题,比如说这个:如何比较 Java 的字符串?访问量足足有 370万+,这不得了啊!说明有很多很多的程序员被这个问题困 ...
- 实战webpack系列02
02. 开始使用webpack 1.1.安装 Webpack可以使用npm安装,新建一个空的练习文件夹(此处命名为webpack sample project),在终端中转到该文件夹后执行下述指令就可 ...
- auto_modify_ip Shell脚本安装
#!/bin/bash # : #This author is DKS #auto modify ip of linux ############################### IP_NAME ...