中国剩余定理,又叫孙子定理。

作为一个梗广为流传。其实它的学名叫中国单身狗定理。

  • 中国剩余定理

  中国剩余定理是来干什么用的呢?

  其实就是用来解同余方程组的。那么什么又是同余方程组呢。

  顾名思义就是n个同余方程。

  形如

  如果只有一个方程的话那么是很容易用exgcd来解决。

  但如果变成n个就需要用到CRT了。

  下面我们言归正传。

  首先我们要知道只有满足m1,m2,mn两两互质才能运用CRT。

  首先,我们令M=Πni=1

  令Mi=M/mi,这样我们就可以满足Mi%mk=0(k!=i)。

  然后我们在构造n个数,对于每一个数ti满足Mi×ti≡1(mod mi),即ti为Mi在mod mi意义下的乘法逆元(好像是这么叫吧),用exgcd可求。

  最后再把所有Mi×ti×ai求和再取模就可以了。

  为什么这样做是正确的呢?因为Mi×ti≡1(mod mi),则Mi×ti×ai≡ai(mod mi)。

  显然,把所有的数加到一起必定满足方程。(切记不要忘了取模)。

  一道模板题LOJ10212

  

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <queue>
#include <vector>
using namespace std;
int m[], a[];
long long qpow(long long a, long long b) {
long long ans = ;
while (b) {
if (b & )
ans = ans * a;
b = b >> ;
a = a * a;
}
return ans;
}
long long exgcd(long long a, long long b, long long &x, long long &y) {
long long t;
if (!b) {
x = ;
y = ;
return a;
}
long long gcd = exgcd(b, a % b, x, y);
t = x;
x = y;
y = t - a / b * y;
return gcd;
}
int main() {
int n;
long long M = ;
scanf("%d", &n);
for (int i = ; i <= n; i++) {
scanf("%d%d", &m[i], &a[i]);
M *= 1ll * m[i];
}
long long ans = ;
for (int i = ; i <= n; i++) {
long long x, y;
long long Mi = M / m[i];
exgcd(Mi, m[i], x, y);
ans += x * Mi * a[i];
}
printf("%lld", (ans % M + M) % M);
}

CRT

  • 拓展中国剩余定理

  在上面CRT讲解中我们提到所有的m必须两两互质,因为如果不两两互质就可能无解或求错。

  但是如果毒瘤出题人就让他们不互质呢。

  那我们就需要把出题人吊起来打一顿用到拓展CRT(实际上他和CRT没有任何关系)

  首先只考虑有两个方程怎么做

  x=a1+k1×m1,x=a2+k2×m2 。可以得到k2×m2-k1×m1=a1-a2。

  嗯,看起来有点像一个二元一次方程了。

  我们令 gcd=gcd(m1,m2),c=a1-a2;

  如果gcd%c!=0则无解

  否则用exgcd来求出k1×m1+k2×m2=gcd的解k1,再乘上c/gcd就好了。

  为了避免爆long long 最好取一下模。

  这样我们就可以反推出x。

  但注意我们解的方程k1项系数为-1,相当与k1=-k1(所以k1=0?)

  这样就求出了x。(可以把这个x0转化成最小的非负数解)
  这个x符合第一个方程,也符合第二个方程。设这个x为x0
  所以,可以得到通解是:x=x0+k×lcm(m1,m2)  
  满足这个条件的x就满足第一第二两个方程。满足第一第二两个方程的所有的解也都是这个方程的解。
  所以第一第二个方程和这个方程是等价的。
  将这个方程转化一下,可以得到新的同余方程:x=x0(modlcm(m1,m2))
  这样,我们成功的把两个方程转化成了一个方程,以此类推。
  最后留下的这个方程,它的x_0的最小非负数解,就是我们要的最终答案(最后这一段用文本编辑器打的,略显不符,请自动忽略)。

  例题 poj2891

  模板题,直接放代码

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
#include<cstdlib>
using namespace std;
#define int long long
int m[],c[];
int exgcd(int a,int b,int &x,int &y){
int t;
if(!b){
x=;y=;
return a;
}
int gcd=exgcd(b,a%b,x,y);
t=x;
x=y;
y=t-a/b*y;
return gcd;
}
signed main(){
int n;
while(~scanf("%lld",&n)){
bool ju=;
for(int i=;i<=n;i++) scanf("%lld%lld",&m[i],&c[i]);
int m1=m[],c1=c[];
for(int i=;i<=n;i++){
int x,y;
int m2=m[i],c2=c[i];
int dembele=exgcd(m1,m2,x,y);
if((c2-c1)%dembele){
ju=;
printf("-1\n");
break;
}
x=(c1-c2)/dembele*x%m2;
c1-=m1*x;
m1=m1/dembele*m2;
c1%=m1;
}
if(ju)
printf("%lld\n",(c1%m1+m1)%m1);
}
}

EXCRT

  

中国剩余定理及其拓展 CRT&EXGCD的更多相关文章

  1. 扩展中国剩余定理(扩展CRT)详解

    今天在$xsy$上翻题翻到了一道扩展CRT的题,就顺便重温了下(扩展CRT模板也在里面) 中国剩余定理是用于求一个最小的$x$,满足$x\equiv c_i \pmod{m_i}$. 正常的$CRT$ ...

  2. 模线性方程&&中国剩余定理及拓展

    一.求解模线性方程 由ax=b(mod n) 可知ax = ny + b 就相当于ax + ny = b 由扩展欧几里得算法可知有解条件为gcd(a, n)整除d 可以直接套用扩展欧几里得算法 最终由 ...

  3. 浅析中国剩余定理(从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(正确性在此不加证明) 下面先看一道题(改 ...

  4. E - Two Arithmetic Progressions(CodeForces - 710D)(拓展中国剩余定理)

    You are given two arithmetic progressions: a1k + b1 and a2l + b2. Find the number of integers x such ...

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

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

  6. 欧几里得(辗转相除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* ...

  7. 中国剩余定理(CRT)及其拓展(ExCRT)

    中国剩余定理 CRT 推导 给定\(n\)个同余方程 \[ \left\{ \begin{aligned} x &\equiv a_1 \pmod{m_1} \\ x &\equiv ...

  8. 拓展中国剩余定理(exCRT)摘要

    清除一个误区 虽然中国剩余定理和拓展中国剩余定理只差两个字,但他俩的解法相差十万八千里,所以会不会CRT无所谓 用途 求类似$$\begin{cases}x \equiv b_{1}\pmod{a_{ ...

  9. POJ.1006 Biorhythms (拓展欧几里得+中国剩余定理)

    POJ.1006 Biorhythms (拓展欧几里得+中国剩余定理) 题意分析 不妨设日期为x,根据题意可以列出日期上的方程: 化简可得: 根据中国剩余定理求解即可. 代码总览 #include & ...

随机推荐

  1. Java Volatile关键字(转)

    出处:  Java Volatile关键字 Java的volatile关键字用于标记一个变量“应当存储在主存”.更确切地说,每次读取volatile变量,都应该从主存读取,而不是从CPU缓存读取.每次 ...

  2. TIPTOP之分割split函数方法、getIndexOf、subString、replace、临时表创建;

    范例(cnmq001): 原:每次查询都把数据全部查询到临时表后再筛选: 现:查询到临时表的时候,增加可行的筛选条件,再二次筛选临时表的数据,进行优化: 1)临时表创建: PRIVATE FUNCTI ...

  3. 国内有哪些好的JAVA社区

    转载自 https://www.zhihu.com/question/29836842#answer-13737722 并发编程网 - ifeve.com 强烈推荐 ImportNew - 专注Jav ...

  4. Java 代码运行顺序

    1.静态代码块,只执行一次,从上到下,先父类后子类 2.父类构造代码块,从上到下,然后父类构造方法,执行次数与实例化次数相关 3.子类构造代码块,从上到下,然后子类构造方法,执行次数与实例化次数相关

  5. 浅读vue-router源码,了解vue-router基本原理

    项目中使用vue-router的时候,会进行以下操作(可能具体不是这么写的,但是原理一样): 定义映射关系routes: 定义router实例的时候传入vue和参数{routes...}: 定义vue ...

  6. vue项目打包文件配置(vue-clli3)

    练手项目完结打包的时候遇到一些问题,特此记录 先贴我的vue.config.js文件的代码(vue-cli3构建的项目默认是没有此文件的,需手动添加)更多详细配置参考官方配置文档,我的项目不大不小,这 ...

  7. UEFI笔记 --- PeiReadOnlyVariable2->GetVariable()

    问:在PEI阶段,PeiReadOnlyVariable2->GetVariable()可以从Pei Hob或NV RAM中获取UEFI变量,例如Setup默认值.若平台首次烧录BIOS并开机, ...

  8. pycharm问题合集

    一  打开pycharm出现 点击右上角的配置之后 配置正确的python路径 又出现 解决办法 删除所有的解释器,据说是重名导致的. 然后在配置一次 二  ModuleNotFoundError: ...

  9. Perl数据类型

    Perl 是一种弱类型语言,所以变量不需要指定类型,Perl 解释器会根据上下文自动选择匹配类型. Perl 有三个基本的数据类型:标量.数组.哈希.以下是这三种数据类型的说明: 标量 标量是Perl ...

  10. 6.Nginx的session一致性(共享)问题配置方案2

    1.利用memcached配置session一致性的另外一种方案tengine的会话保持功能 1.1:Tengine会话保持:通过cookie来实现的 该模块是一个负载均衡模块,通过cookie实现客 ...