中国剩余定理

问题引入:

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

就是计算一个数\(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. Facetoprocess_program_design

    面向过程程序设计 程序:计算机用可理解可执行的命令的集合. 过程:问题解决的步骤. 方法(函数) 结构化程序设计的基础 一.方法三要素 1 功能: 实现的功能(单一).简单.易维护 2 参数: (传入 ...

  2. node解决跨域和服务器代理详解代码

    node中有很多解决服务器代理的插件,这里简介一个:express-http-proxy 之前网上查的使用node解决跨域的插件,有很多,例如,cors,koa2,这里解决跨域问题我拿原生解决的,ex ...

  3. 【Java基础】IO 流

    IO 流 File 类 java.io.File 类是文件和文件目录路径的抽象表示形式,与平台无关. File 能新建.删除.重命名文件和目录,但 File 不能访问文件内容本身. 如果需要访问文件内 ...

  4. Java 用java GUI写一个贪吃蛇小游戏

    目录 主要用到 swing 包下的一些类 上代码 游戏启动类 游戏数据类 游戏面板类 代码地址 主要用到 swing 包下的一些类 JFrame 窗口类 JPanel 面板类 KeyListener ...

  5. dmp文件导入抽取方法

    一.确认dmp文件.oracle客户端和服务端的字符集 (1)dmp文件字符集确认: 使用UE打开dmp文件查看文件第2个和第3个字节内容,这两个字节记录了dmp文件的字符集.如0354,然后用以下s ...

  6. Unsafe Fileupload - Pikachu

    概述: 文件上传功能在web应用系统很常见,比如很多网站注册的时候需要上传头像.上传附件等等.当用户点击上传按钮后,后台会对上传的文件进行判断 比如是否是指定的类型.后缀名.大小等等,然后将其按照设计 ...

  7. k8s中教你快速写一条yaml文件

    一条yaml中有很多字段,如果去背这些字段,其实也能背过,但是去写一条yaml,也往往浪费很多的时间,也会出错,其实我们可以用一条命令就能快速来写一段自定义的yaml,工作中去修改相应的yaml也得心 ...

  8. Java运算符概要与数学函数

    运算符概要 在Java中,使用算术运算符+,-,*,/表示加减乘除运算,当参与/的运算的两个操作数都是整数时,表示整数除法,否则,表示浮点除法.整数的求余操作(有时称为取模),用%表示,例如,15/2 ...

  9. linux下安装zsh和p10k的详细过程

    目录 下载zsh 下载oh-my-zsh 切换shell 下载p10k 下载zsh sudo apt-get install zsh sudo apt-get install git 下载oh-my- ...

  10. Vue案例之todoLIst实现

    使用Vue实现todolist案例,如有不对敬请大佬多多指教 功能: 1.增加功能:在新增版块里面的输入框内输入数据,点击后面的"添加"按钮,将输入的数据添加到列表中,默认是未完成 ...