扩展中国剩余定理详解
前言
阅读本文前,推荐先学一下中国剩余定理。其实不学也无所谓,毕竟两者没啥关系
扩展CRT
我们知道,中国剩余定理是用来解同余方程组
begin{cases}xequiv c_{1}left( mod m_{1}right) \ xequiv c_{2}left( mod m_{2}right) \ ldots \ xequiv c_rleft( mod m_rright) end{cases}
但是有一个非常令人不爽的事情就是它要求m_1,m_2ldots,m_r两两互素
如果某个毒瘤出题人偏要求它们部互素呢?
其实也有解决的办法
就是把出题人吊起来干一顿用扩展中国剩余定理
扩展中国剩余定理跟中国剩余定理没半毛钱关系,一个是用扩展欧几里得,一个是用构造
首先我们还是从简单入手,考虑一下如果同余方程组只有两个式子的情况
xequiv c_{1}left( mod m_{1}right) \ xequiv c_{2}left( mod m_{2}right)
将两个式子变形
x=c_{1}+m_{1}k_{1}\ x=c_{2}+m_{2}k_{2}
联立
c_{1}+m_{1}k_{1}=c_{2}+m_{2}k_{2}
移项
m_{1}k_{1}=c_{2}-c_{1}+m_{2}k_{2}
我们用$(a,b)$表示$a,b$的最大公约数
在这里需要注意,这个方程有解的条件是
left( m_{1},m_{2}right) |left( c_{2}-c_{1}right),因为后面会用到dfrac {left( c_{2}-c_{1}right) }{left( m_{2},m_{1}right) }这一项,如果不整除的话肯定会出现小数。
对于上面的方程,两边同除$(m_1,m_2)$
dfrac {m_{1}k_{1}}{left( m_{1},m_{2}right) }=dfrac {c_{2}-c_{1}}{left( m_{1},m_{2}right) }+dfrac {m_{2}k_{2}}{left( m_{1},m_{2}right) }
dfrac {m_{1}}{left( m_{1},m_{2}right) }k_{1}=dfrac {c_{2}-c_{1}}{left( m_{1},m_{2}right) }+dfrac {m_{2}}{left( m_{1},m_{2}right) }k_{2}
转换一下
dfrac {m_{1}}{left( m_{1},m_{2}right) }k_{1} equiv dfrac {c_{2}-c_{1}}{left( m_{1},m_{2}right) } (mod dfrac {m_{2}}{left( m_{1},m_{2}right) })
此时我们已经成功把$k_2$消去了。
同余式两边同除dfrac {m_{1}}{left( m_{1},m_{2}right) }
k_1equiv inv({m_1over(m_1,m_2)},{m_2over (m_1,m_2)})*{(c_2-c_1)over (m_1,m_2)}pmod {{m_2over(m_1,m_2)}}
inv(a,b)表示a在模b意义下的逆元
k_1=inv({m_1over(m_1,m_2)},{m_2over (m_1,m_2)})*{(c_2-c_1)over (m_1,m_2)}+{{m_2over (m_1,m_2)}}*y
接下来怎么办呢?这个式子已经化到最简了。。
不要忘了,我们刚开始还有两个式子。我们把k_1待回去!
x=inv({m_1over(m_1,m_2)},{m_2over (m_1,m_2)})*{(c_2-c_1)over (m_1,m_2)}*m_1+y{{m_1m_2over (m_1,m_2)}}+c_1
xequiv inv({m_1over(m_1,m_2)},{m_2over (m_1,m_2)})*{(c_2-c_1)over (m_1,m_2)}*m_1+c_1pmod {{m_1m_2over (m_1,m_2)}}
此时,整个式子中的元素我们都已经知道了
具体一点,这个式子可以看做是xequiv cpmod m
其中c=(inv({m_1over (m_1,m_2)},{m_2over (m_1,m_2)})*{(c_2-c_1)over (m_1,m_2)})%{m_2over (m_1,m_2)}*m_1+c_1
m={m_1m_2over (m_1,m_2)}
推广一下
我们每次把两个同余式合并,求解之后得到一个新的同余式。再把新的同余式和其他的联立,最终就可以求出满足条件的解
代码
#include<iostream>
#include<cstdio>
#define LL long long
using namespace std;
const LL MAXN=1e6+10;
LL K,C[MAXN],M[MAXN],x,y;
LL gcd(LL a,LL b)
{
return b==0?a:gcd(b,a%b);
}
LL exgcd(LL a,LL b,LL &x,LL &y)
{
if(b==0){x=1,y=0;return a;}
LL r=exgcd(b,a%b,x,y),tmp;
tmp=x;x=y;y=tmp-(a/b)*y;
return r;
}
LL inv(LL a,LL b)
{
LL r=exgcd(a,b,x,y);
while(x<0) x+=b;
return x;
}
int main()
{
#ifdef WIN32
freopen("a.in","r",stdin);
#else
#endif
while(~scanf("%lld",&K))
{
for(LL i=1;i<=K;i++) scanf("%lld%lld",&M[i],&C[i]);
bool flag=1;
for(LL i=2;i<=K;i++)
{
LL M1=M[i-1],M2=M[i],C2=C[i],C1=C[i-1],T=gcd(M1,M2);
if((C2-C1)%T!=0) {flag=0;break;}
M[i]=(M1*M2)/T;
C[i]= ( inv( M1/T , M2/T ) * (C2-C1)/T ) % (M2/T) * M1 + C1;
C[i]=(C[i]%M[i]+M[i])%M[i];
}
printf("%lldn",flag?C[K]:-1);
}
return 0;
}
再放道裸题
http://acm.hdu.edu.cn/showproblem.php?pid=1573
- iOS textfield实现一行的数字限制,超出进行弹框
- android https安全连接
- 第二章 正则表达式位置匹配攻略
- 从网络上下载省份城市名称并存入文件然后进行读取省份城市
- android 应用模式之mvp
- Android网络请求框架之Retrofit实践
- iOS 跳转到应用所在的App Store市场
- 第一章 正则表达式字符匹配攻略
- js最新手机号码、电话号码正则表达式
- iOS afnetworking最新版报错 没有AFHTTPRequestOperationManager类了
- Android Service学习之本地服务
- iOS .pch文件的使用
- CountDownTimer说明及使用
- UiTextField对输入的长度进行限制并提示用户还可输入的长度
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Python自学成才之路 多进程开发
- Python自学成才之路 进程间通信
- android 功耗(1)---android 功耗分析方法和优化
- 为什么要写 tf.Graph().as_default()
- tf.get_variable_scope().reuse_variables() 的使用
- Tensorflow小技巧整理:
- Tensorflow学习笔记——Summary用法
- 神经网络优化(损失函数:自定义损失函数、交叉熵、softmax())
- C++ STL stack 用法
- 遍历string时 使用for(char& c : s) for(char c : s) 的区别
- vc dll静态函数导出
- 利用GDB调试 MSQL
- 手把手教学-MySQL主从复制架构转换MGR架构(mysq_shell版)
- 手把手教学-MySQL主从复制架构转换MGR架构(手动版)
- 云数据库VS自建数据库,到底该如何抉择?