中国剩余定理

问题引入:

有物不知其数,三三数之剩二,五五数之剩三,七七数之剩二。问物几何?《孙子算经》

就是计算一个数\(x\)满足\(\begin{cases} x≡2(MOD\ 3) \\ x≡3(MOD\ 5) \\ x≡2(MOD\ 7) \end{cases}\)

中国剩余定理:

首先对于同余方程,以下等式显然成立:

\[(\sum a_i)\%p ≡ \sum (a_i\%p)\ (MOD\ p)①
\]

接下来我们构造三个数\(a,b,c\)满足以下条件:

\[\left[ \begin{array}{ccc}
a\%3=2 & a\%5=0 & a\%7=0 \\
b\%3=0 & b\%5=3 & b\%7=0 \\
c\%3=0 & c\%5=0 & c\%7=2
\end{array} \right]\]

可以发现根据等式\(①\),\(a+b+c\)即为所求\(x\)的一个解

现在考虑如何构造\(a,b,c\)三个数

首先\(a\)是\(5\)的倍数也是\(7\)的倍数,所以\(a\)是\(35\)的倍数,同理,\(b\)是\(21\)的倍数,\(c\)是\(15\)的倍数

所以令

\[\begin{cases}
a = 35\cdot k_a \\
b = 21\cdot k_b \\
c = 15\cdot k_c
\end{cases}\]

\[\begin{cases}
35\cdot k_a ≡ 2\ (MOD\ 3)\\
21\cdot k_b ≡ 3\ (MOD\ 5)\\
15\cdot k_c ≡ 2\ (MOD\ 7)
\end{cases}\]

设\(35\)在模\(3\)意义下的逆元为\(inv_a\),\(21\)在模\(5\)意义下的逆元为\(inv_b\),\(15\)在模\(7\)下的逆元为\(inv_c\)

\(inv_a = 2,inv_b = 1,inv_c = 1\)

\[\begin{cases}
k_a = 2\cdot inv_a = 4\\
k_b = 3\cdot inv_b = 3\\
k_c = 2\cdot inv_c = 2
\end{cases}
\]

所以:

\[\begin{cases}
a = 140\\
b = 63\\
c = 30
\end{cases}
\]

所以得到\(x\)的一个解\(x=a+b+c=233\)

如果要求得所有\(x\)中最小的非负整数解,只要用\(x\)对\(lcm(3,5,7)\)取模即可

所以最后得到的最小的\(x = 233\%(3\cdot 5\cdot 7)=23\)

推广到一般情况下:

\[求出最小的x满足:
\begin{cases}
x ≡ r_1\ (MOD\ p_1)\\
x ≡ r_2\ (MOD\ p_2)\\
\quad \quad \quad \vdots\\
x ≡ r_m\ (MOD\ p_m)\\
\end{cases},其中\forall gcd(p_i,p_j)=1\]
\[记 P = \prod_{i=1}^{m}p_i,inv_i为\frac{P}{p_i}在模p_i意义下的逆元
\]
\[在模P意义下得到x的唯一解:x = (\sum_{i=1}^{m}r_i\cdot \frac{P}{p_i}\cdot inv_i)\%P
\]

例题:

HDU1370 Biorhythms

view code
//#pragma GCC optimize("O3")
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
typedef long long int LL;
const LL p[3] = {23,28,33};
void exgcd(LL a, LL b, LL &x, LL &y){
if(!b){ x = 1; y = 0; return; }
exgcd(b,a%b,y,x);
y -= a / b * x;
}
void solve(LL a[], LL d, int kase){
for(int i = 0; i < 3; i++) a[i] %= p[i];
LL P = p[0] * p[1] * p[2], sum = 0;
for(int i = 0; i < 3; i++){
LL inv, y;
exgcd(P/p[i],p[i],inv,y);
sum = (sum + P/p[i]*inv%P*a[i]%P) % P;
}
LL day = (sum%P+P)%P - d; if(day<=0) day += P;
printf("Case %d: the next triple peak occurs in %I64d days.\n",kase,day);
}
int main(){
int tt; ____();
for(cin >> tt; tt; tt--){
LL a[3], d;
int kase = 1;
while(cin >> a[0] >> a[1] >> a[2] >> d and (a[0]+a[1]+a[2]+d+4)) solve(a,d,kase++);
}
return 0;
}

扩展中国剩余定理

\[求解线性同余方程组:
\begin{cases}
x ≡ r_1\ (MOD\ p_1) \\
x ≡ r_2\ (MOD\ p_2) \\
\quad \quad \quad \vdots \\
x ≡ r_m\ (MOD\ p_m)
\end{cases}
,\exists gcd(p_i,p_j)\ne 1
\]

首先考虑两个同余方程:

\[\begin{cases}
x ≡ r_1\ (MOD\ p_1) \\
x ≡ r_2\ (MOD\ p_2)
\end{cases}
,gcd(p_1,p_2)\ne 1
\]

可以得到:

\[p_1 \cdot k_1 + r_1 = p_2 \cdot k_2 + r_2\]
\[\Downarrow
\]
\[p_1 \cdot k_1 - p_2 \cdot k_2 = r_2 - r_1
\]

根据裴蜀定理,\((r_2-r_1) \% gcd(p_1,p_2)\ne 0\)的情况下是无解的

在\((r_2-r_1) \% gcd(p_1,p_2) = 0\)的情况下,可以通过扩展欧几里得求得\(k_1\)和\(k_2\)

然后就可以得到:

\[x ≡ p_1\cdot k_1 + r_1\ (MOD\ lcm(p_1,p_2))
\]
\[OR
\]
\[x ≡ p_2\cdot k_2 + r_2\ (MOD\ lcm(p_1,p_2))
\]

对于多个方程的情况下,两两合并即可

例题:

洛谷P4777

view code
//#pragma GCC optimize("O3")
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
typedef long long int LL;
LL ksc(LL a, LL b, LL mod){
LL ret = 0;
int flag = ((a<0)^(b<0)) ? -1 : 1;
a = abs(a); b = abs(b);
while(b){
if(b&1) ret = (ret + a) % mod;
b >>= 1;
a = (a + a) % mod;
}
return ret * flag;
}
LL exgcd(LL a, LL b, LL &x, LL &y){
if(!b){ x = 1, y = 0; return a; }
LL g = exgcd(b,a%b,y,x);
y -= a/b*x;
return g;
}
pair<LL,LL> excrt(LL b1, LL p1, LL b2, LL p2){
LL d = b2 - b1, x, y;
LL g = exgcd(p1,p2,x,y);
LL p = p1 / g * p2;
x = ksc(x,d/g,p);
return make_pair(((ksc(x,p1,p)+b1)%p+p)%p,p);
}
int main(){
____();
int n;
LL b, p;
cin >> n >> p >> b;
for(int i = 1; i < n; i++){
LL bb, pp;
cin >> pp >> bb;
tie(b,p) = excrt(b,p,bb,pp);
}
cout << b << endl;
return 0;
}

(EX)中国剩余定理的更多相关文章

  1. 《孙子算经》之"物不知数"题:中国剩余定理

    1.<孙子算经>之"物不知数"题 今有物不知其数,三三数之剩二,五五数之剩七,七七数之剩二,问物几何? 2.中国剩余定理 定义: 设 a,b,m 都是整数.  如果 m ...

  2. POJ 1006 中国剩余定理

    #include <cstdio> int main() { // freopen("in.txt","r",stdin); ; while(sca ...

  3. [TCO 2012 Round 3A Level3] CowsMooing (数论,中国剩余定理,同余方程)

    题目:http://community.topcoder.com/stat?c=problem_statement&pm=12083 这道题还是挺耐想的(至少对我来说是这样).开始时我只会60 ...

  4. poj1006中国剩余定理

    Biorhythms Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 103506   Accepted: 31995 Des ...

  5. (伪)再扩展中国剩余定理(洛谷P4774 [NOI2018]屠龙勇士)(中国剩余定理,扩展欧几里德,multiset)

    前言 我们熟知的中国剩余定理,在使用条件上其实是很苛刻的,要求模线性方程组\(x\equiv c(\mod m)\)的模数两两互质. 于是就有了扩展中国剩余定理,其实现方法大概是通过扩展欧几里德把两个 ...

  6. 洛谷P2480 [SDOI2010]古代猪文(费马小定理,卢卡斯定理,中国剩余定理,线性筛)

    洛谷题目传送门 蒟蒻惊叹于一道小小的数论题竟能涉及这么多知识点!不过,掌握了这些知识点,拿下这道题也并非难事. 题意一行就能写下来: 给定\(N,G\),求\(G^{\sum \limits _{d| ...

  7. 洛谷P3868 [TJOI2009]猜数字(中国剩余定理,扩展欧几里德)

    洛谷题目传送门 90分WA第二个点的看过来! 简要介绍一下中国剩余定理 中国剩余定理,就是用来求解这样的问题: 假定以下出现数都是自然数,对于一个线性同余方程组(其中\(\forall i,j\in[ ...

  8. POJ2891 Strange Way to Express Integers 扩展欧几里德 中国剩余定理

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - POJ2891 题意概括 给出k个同余方程组:x mod ai = ri.求x的最小正值.如果不存在这样的x, ...

  9. hihocode 九十七周 中国剩余定理

    题目1 : 数论六·模线性方程组 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Ho:今天我听到一个挺有意思的故事! 小Hi:什么故事啊? 小Ho:说秦末,刘邦的将军 ...

  10. hdu 3579 Hello Kiki 不互质的中国剩余定理

    Hello Kiki Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Probl ...

随机推荐

  1. 卷积神经网络学习笔记——Siamese networks(孪生神经网络)

    完整代码及其数据,请移步小编的GitHub地址 传送门:请点击我 如果点击有误:https://github.com/LeBron-Jian/DeepLearningNote 在整理这些知识点之前,我 ...

  2. MATLAB OPC错误OPCenum service is not operating correctly解决办法

    错误截图: 出错原因:C:\Windows\SysWOW64下没有OpcEnum.exe等文件,opc需要这些文件才能正常运行.有些系统内置了,有些系统没有. 解决方法:去opc官网https://o ...

  3. 【Azure Developer】使用Postman获取Azure AD中注册应用程序的授权Token,及为Azure REST API设置Authorization

    Azure Active Directory (Azure AD) is Microsoft's cloud-based identity and access management service, ...

  4. docker搭建前端环境

    开发环境的搭建,是新人入职后的第一道槛,有时一个小小的问题就能阻塞半天.如果能提供一个工具在短时间内搞定开发环境,势必提高新人对团队的印象分!docker就是这样一个工具. 镜像&容器 doc ...

  5. 天梯赛练习 L3-016 二叉搜索树的结构 (30分)

    题目分析: 用数型结构先建树,一边输入一边建立,根节点的下标为1,所以左孩子为root*2,右孩子为root*2+1,输入的时候可用cin输入字符串也可用scanf不会超时,判断是否在同一层可以判断两 ...

  6. PC个人隐私保护小方法

    前言 近期爆出了腾讯读取用户浏览器浏览记录的消息.话不过说直接上图,懂的自然懂. 网上也有详细的分析文章,不管它读取后用来做什么,在你不知情的情况下读取了你的浏览器浏览记录,你说气不气. 虽然在整体大 ...

  7. 我在华为OD的275天

    目录 0 - 时间线 1 - 为什么会去华为 OD 2 - 华为 OD 的工作内容 3 - OD 与华为自有员工的对比 4 - 那,到底要不要去华为 OD? 5 - 网传的 OD 转华为正编,真的假的 ...

  8. JMeter联机负载及问题解决

    主控制机:存放JMeter脚本的机器叫做主控制机 负载机:被连接并用来运行脚本的机器叫做负载机 操作步骤: 1.修改主控制机上,JMeter安装目录bin目录下的JMeter.properties文件 ...

  9. .net core 和 WPF 开发升讯威在线客服与营销系统:使用 TCP协议 实现稳定的客服端

    本系列文章详细介绍使用 .net core 和 WPF 开发 升讯威在线客服与营销系统 的过程.本产品已经成熟稳定并投入商用. 在线演示环境:https://kf.shengxunwei.com 注意 ...

  10. Netty之ChannelHandler

    一.概述 handler是控制socket io的各个生命周期的业务实现,netty实现了很多种协议所以有很多handler类,这儿主要关注Handler的设计.作用以及使用方法. 二.Channel ...