updata on 2020.4.11

修正了 excrt 的一处笔误

CRT

求解方程:

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

其中,保证\(m_i\)是两两互质的正整数,crt就是基于这个特征

我们记\(M=\prod_{i=1}^{n} m_i\),和\(M_i=\dfrac{M}{m_i}\),\(t_i\)满足\(M_it_i \equiv 1 \pmod {m_i}\)

即\(M_i\)是所有下标不为\(i\)的\(m\)乘起来,而\(t_i\)是\(M_i \bmod m_i\)的逆元

则对于任意的\(k\neq i\),\(a_iM_it_i\equiv 0\pmod {m_k}\),因为\(M_i\)中一定包含了\(m_k\)这个因数

而又因为\(M_it_i\equiv1\pmod{m_i}\),所以\(a_iM_it_i\equiv a_i\pmod{m_i}\)

所以可以说明

\[\sum_{i=1}^n a_iM_it_i
\]

为问题的一组解,且这个解在\(\mod M\)下唯一

当然通解就是\(x+kM,k\subset Z\)

当然求逆元的过程要用到exgcd,而题目要求最小正整数解,所以只要让解在\([0,M-1]\)中就行了

但是,如果直接\(M=\prod_{i=1}^n m_i\)会乘爆,要让\(M=\text{LCM}_{i=1}^n m_i\),可以有和上文叙述的一样的性质,下面的excrt也是一样

题目代码

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<iomanip>
#include<cstring>
#define reg register
#define EN std::puts("")
#define LL long long
inline int read(){
int x=0,y=1;
char c=std::getchar();
while(c<'0'||c>'9'){if(c=='-') y=0;c=std::getchar();}
while(c>='0'&&c<='9'){x=x*10+(c^48);c=std::getchar();}
return y?x:-x;
}
int n;
LL a[15],m[15],M=1;
void exgcd(LL a,LL b,LL &x,LL &y){
if(!b){
x=1;y=0;
return;
}
exgcd(b,a%b,x,y);
LL tmp=x;x=y;
y=tmp-a/b*y;
}
int main(){
n=read();
for(reg int i=1;i<=n;i++){
m[i]=read();a[i]=read();
M=M/std::__gcd(M,m[i])*m[i];
}
LL ans=0,Mi,x,y;
for(reg int i=1;i<=n;i++){
Mi=M/m[i];
exgcd(Mi,m[i],x,y);
ans=((ans+Mi*x*a[i])%M+M)%M;
}
std::printf("%lld",ans);
return 0;
}

EXCRT

还是求解方程:

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

但这次不保证\(m_i\)两两互质

不过这好像和CRT关系不大

考虑用数学归纳法,假设我们已知前\(i-1\)的解为\(ans\),并记\(M=\text{LCM}_{k=1}^{i-1}m_k\) 则其通解为\(ans+M\times t\)

那么,我们就要确定一个\(t\),使得\(ans+M\times t\equiv a_i\pmod {m_i}\)

然后新的\(ans=ans+M\times t\)

考虑求解上面那个同余方程的方法

因为exgcd可以求解方程\(ax+by=\gcd(a,b)\)

那么我们转变那个同余方程的形式:

\[Mt\equiv a_i-ans \pmod{m_i}
\]

\[Mt+m_iy=a_i-ans
\]

那么如果\(\gcd(M,m_i)|(a_i-ans)\),则有解,题目保证了有解

用exgcd求出的是:

\[Mt'+m_iy=\gcd(M,m_i)
\]

那么让等式两边同时除以这个\(\gcd\)再同时乘以\(a_i-ans\)就行了

\[Mt'\dfrac{(a_i-ans)}{\gcd(M,m_i)}+m_iy\dfrac{(a_i-ans)}{\gcd(M,m_i)}=a_i-ans
\]

那我们要求的这个\(t\)就是\(t'\dfrac{(a_i-ans)}{\gcd(M,m_i)}\)

注意在乘的时候会爆long long,要用int128或是龟速乘

我才不会告诉你们我快读不开long long见祖宗了

还有就是要通过\(ans=(ans+M)\bmod M\)来保证\(ans\)是正的

上代码,因为不开long long那事调了好长时间。。

P4777 【模板】扩展中国剩余定理(EXCRT)

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<iomanip>
#include<cstring>
#define reg register
#define EN std::puts("")
#define LL long long
inline LL read(){
LL x=0,y=1;
char c=std::getchar();
while(c<'0'||c>'9'){if(c=='-') y=0;c=std::getchar();}
while(c>='0'&&c<='9'){x=x*10+(c^48);c=std::getchar();}
return y?x:-x;
}
int n;
LL a[100006],m[100006];
inline LL mul(LL n,LL k,LL mod){
LL ans=0;
while(k){
if(k&1) ans=(ans+n)%mod;
k>>=1;
n=(n+n)%mod;
}
return ans;
}
LL exgcd(LL a,LL b,LL &x,LL &y){
if(!b){x=1;y=0;return a;}
LL ret=exgcd(b,a%b,x,y);
LL z=x;x=y;y=z-(a/b)*y;
return ret;
}
inline LL excrt(){
LL x,y;
LL M=m[1],ans=a[1];
for(reg int i=2;i<=n;i++){
LL b=((a[i]-ans)%m[i]+m[i])%m[i];
LL gcd=exgcd(M,m[i],x,y);
x=mul(x,b/gcd,m[i]);
ans+=M*x;
M*=m[i]/gcd;
ans=(ans+M)%M;
}
return ans;
}
int main(){
n=read();
for(reg int i=1;i<=n;i++) m[i]=read(),a[i]=read();
std::printf("%lld",excrt());
return 0;
}

 

话说去年暑假在洛谷网校就学过一遍crt和excrt了

但当时就没怎么理解清楚,更写不出代码

这次是因为扩展卢卡斯要用到crt,才来写了一遍这两个题。。。

P1495 CRT,P4777 EXCRT的更多相关文章

  1. 「算法笔记」CRT 与 exCRT

    一.扩展欧几里得 求解方程 \(ax+by=\gcd(a,b)\). int exgcd(int a,int b,int &x,int &y){ if(!b) return x=1,y ...

  2. CRT和EXCRT学习笔记

    蒟蒻maomao终于学会\(CRT\)啦!发一篇博客纪念一下(还有防止忘掉) \(CRT\)要解决的是这样一个问题: \[x≡a_1​(mod m_1​)\] \[x≡a_2​(mod m_2​)\] ...

  3. CRT和EXCRT简单学习笔记

    中国剩余定理CRT 中国剩余定理是要求我们解决这样的一类问题: \[\begin{cases}x\equiv a_1\pmod {b_1} \\x\equiv a_2 \pmod{b_2}\\...\ ...

  4. 浅析中国剩余定理(从CRT到EXCRT))

    前置知识 1. a%b=d,c%b=e, 则(a+c)%b=(d+e)%b(正确性在此不加证明) 2. a%b=1,则(d\(\times\)a)%b=d%b(正确性在此不加证明) 下面先看一道题(改 ...

  5. Algorithm: CRT、EX-CRT & Lucas、Ex-Lucas

    中国剩余定理 中国剩余定理,Chinese Remainder Theorem,又称孙子定理,给出了一元线性同余方程组的有解判定条件,并用构造法给出了通解的具体形式. \[ \begin{aligne ...

  6. 关于一次同余方程的一类解法(exgcd,CRT,exCRT)

    1.解同余方程: 同余方程可以转化为不定方程,其实就是,这样的问题一般用拓展欧几里德算法求解. LL exgcd(LL a,LL b,LL &x,LL &y){ if(!b){ x=; ...

  7. 中国剩余定理(CRT)及其扩展(EXCRT)详解

    问题背景   孙子定理是中国古代求解一次同余式方程组的方法.是数论中一个重要定理.又称中国余数定理.一元线性同余方程组问题最早可见于中国南北朝时期(公元5世纪)的数学著作<孙子算经>卷下第 ...

  8. 中国剩余定理(CRT)

    只看懂了CRT,EXCRT待补.... 心得:记不得这是第几次翻CRT了,每次都有迷迷糊糊的.. 中国剩余定理用来求解类似这样的方程组: 求解的过程中用到了同余方程. x=a1( mod x1) x= ...

  9. $NOIp2018$劝退记

    鸽子博主好久没更博了,这一更可能以后都更不了了啊 \(Day~~1\) 考试爆零,已经无所畏惧了. 当作攒rp吧...qwq 晚上写了写数学总结,蒯了一堆人的博客资料,然后就学会了\(CRT\),\( ...

随机推荐

  1. Linux学习,path,环境变量的配置

    方法一: 1.查看当前环境变量配置的所与信息 echo $PATH 注意: echo是输出的意思 加$表示它是一个变量 2.配置环境命令 PATH="$PATH":comdir 注 ...

  2. C++11中的四种类型转换

    static_cast 基础数据类型转换(基本类型) 同一继承体系中类型的转换(父子类型) 任意类型与空指针(void *)之间的转换(指针类型) dynamic_cast 执行派生类指针或引用与基类 ...

  3. 让 .NET 轻松构建中间件模式代码(二)

    让 .NET 轻松构建中间件模式代码(二)--- 支持管道的中断和分支 Intro 上次实现了一个基本的构建中间件模式的中间件构建器,现在来丰富一下功能,让它支持中断和分支,分别对应 asp.net ...

  4. 【Selenium05篇】python+selenium实现Web自动化:读取ini配置文件,元素封装,代码封装,异常处理,兼容多浏览器执行

    一.前言 最近问我自动化的人确实有点多,个人突发奇想:想从0开始讲解python+selenium实现Web自动化测试,请关注博客持续更新! 这是python+selenium实现Web自动化第五篇博 ...

  5. VulnHub靶场学习_HA: ARMOUR

    HA: ARMOUR Vulnhub靶场 下载地址:https://www.vulnhub.com/entry/ha-armour,370/ 背景: Klaw从“复仇者联盟”超级秘密基地偷走了一些盔甲 ...

  6. SpringCloud系列之网关(Gateway)应用篇

    @ 目录 前言 项目版本 网关访问 鉴权配置 限流配置 前言 由于项目采用了微服务架构,业务功能都在相应各自的模块中,每个业务模块都是以独立的项目运行着,对外提供各自的服务接口,如没有类似网关之类组件 ...

  7. 初识指令重排序,Java 中的锁

    本文是作者原创,版权归作者所有.若要转载,请注明出处.本文只贴我觉得比较重要的源码 指令重排序 Java语言规范JVM线程内部维持顺序化语义,即只要程序的最终结果与它顺序化情况的结果相等,那么指令的执 ...

  8. 用Taro做个微信小程序Todo, 小白工作记录

    微信小程序框架: Taro 做微信小程序的框架, 几个比较主流的: 官方的WePY: https://tencent.github.io/wepy/document.html#/ 美团的mpvue: ...

  9. Hbase的安装与基本操作

    简介: 1安装 HBase​   本节介绍HBase的安装方法,包括下载安装文件.配置环境变量.添加用户权限等. 1.1 下载安装文件   HBase是Hadoop生态系统中的一个组件,但是,Hado ...

  10. Scrapy模拟登录信息

    携带cookie模拟登录 需要在爬虫里面自定义一个start_requests()的函数 里面的内容: def start_requests(self): cookies = '真实有效的cookie ...