欧几里得(辗转相除gcd)、扩欧(exgcd)、中国剩余定理(crt)、扩展中国剩余定理(excrt)简要介绍
1.欧几里得算法(辗转相除法)
直接上gcd和lcm代码。
int gcd(int x,int y){
return y==?x:gcd(y,x%y);
}
int lcm(int x,int y){
return x*y/gcd(x,y);
}
2.扩欧:exgcd:对于a,b,一定存在整数对(x,y)使ax+by=gcd(a,b)=d ,且a,b互质时,d=1。 x,y可递归地求得。
我懒得改返回值类型了
long long exgcd(long long a,long long b,long long &x,long long &y){
long long d=a;
if(b==) y=,x=;
else{
d = exgcd(b,a%b,y,x);
y -= a/b*x;
}
return d;
}
求解 x,y的方法的理解:
设 a>b。
1,显然当 b=0,gcd(a,b)=a。此时 x=1,y=0;
2,a>b>0 时
设 ax1+ by1= gcd(a,b);
bx2+ (a mod b)y2= gcd(b,a mod b);
根据朴素的欧几里德原理有 gcd(a,b) = gcd(b,a mod b);
则:ax1+ by1 = bx2+ (a mod b)y2;
即:ax1+ by1 = bx2+ (a - [a / b] * b)y2
= ay2+ bx2- [a / b] * by2;
= ay2+ b(x2- [a / b] *y2);
所以:x1=y2; y1=x2- [a / b] *y2;
这样我们就得到了求解 x1,y1 的方法:x1,y1 的值基于 x2,y2.
这个思想是递归的,因为 gcd 不断的递归求解一定会有个时候 b=0,所以递归可以结束。
3.中国剩余定理(Chinese remainder theorem)
截自百度百科:
要求模下的唯一解,关键是求逆元。
拓展欧几里得如何求逆元:
当a与b互素时有 gcd(a ,b)=1
即得: a*x+b*y=1
a*x ≡ 1 (mod b)
由于a与b互素,同余式两边可以同除a 得:1*x ≡ 1/a (mod b),因此 x 是 a mod b 的逆元;
求逆元也可单写为函数:a在模b意义下的逆元:inv(a,b);
long long inv(long long a, long long b){
exgcd(a,b,x,y);
while(x<) x+=b;
return x;
}
51nod中还有个求乘法逆元的题,直接应用扩欧求逆元即可。
最后上crt完整代码:
long long crt(){//pri数组和re数组分别保存质数和余数 也就是上图方程组中的mi和ai
long long m=,ans=;
for(int i=;i<n;i++){
m*=pri[i];
}
for(int i=;i<n;i++){
long long mi=m/pri[i],x,y;
exgcd(mi,pri[i],x,y); //exgcd的应用:求得逆元x
ans=(ans+re[i]*x*mi)%m;//加和求模下的唯一解
}
while(ans<) ans+=m;
return ans;
}
例题:51nod 1079中国剩余定理 http://www.51nod.com/Challenge/Problem.html#!#problemId=1079
#include <iostream>
using namespace std;
int n;
long long pri[],re[];//分别保存质数,和取余的结果
//利用扩展欧几里得求乘法取模运算的逆元
long long exgcd(long long a,long long b,long long &x,long long &y){
long long d=a;
if(b==) y=,x=;
else{
d=exgcd(b,a%b,y,x);
y-=a/b*x;
}
return d;
}
//Chinese remainder theorem
long long crt(){
long long m=,ans=;
for(int i=;i<n;i++){
m*=pri[i];
}
for(int i=;i<n;i++){
long long mi=m/pri[i],x,y;
exgcd(mi,pri[i],x,y);
ans=(ans+re[i]*x*mi)%m;
}
if(ans<) ans+=m;
return ans;
}
int main(){
cin>>n;
for(int i=;i<n;i++){
cin>>pri[i]>>re[i];
}
cout<<crt()<<endl;
return ;
}
4.扩展中国剩余定理(excrt)
如果人家给的除数不是质数怎么办?就要先处理线性同余方程组了。
我太笨了当时看了好久还是不会,现在稍微明白点了但还是迷迷糊糊,具体分析过程可以看这个dalao的blog,过程很详细:https://www.cnblogs.com/zwfymqz/p/8425731.html
放一个参考人家修修改改写的题目吧。POJ2891
#include<iostream>
#include<cstdio>
#define ll long long
using namespace std; const ll MAXN = 1e6 + ;
ll K, C[MAXN], M[MAXN], x, y; ll gcd(ll a, ll b) {
return b == ? a : gcd(b, a % b);
}
ll exgcd(ll a, ll b, ll &x, ll &y) {
ll r=a;
if (b == ) x = , y = ;
else{
r = exgcd(b, a % b, y, x);
y -= (a / b) * x;
}
return r;
}
ll inv(ll a , ll b){//求逆元
exgcd(a,b,x,y);
while(x<) x+=b;
return x;
} int main(){
while(cin>>K){
for (ll i = ; i <= K; i++) scanf("%lld%lld", &M[i], &C[i]);
bool flag = ;
for (ll i = ; i <= K; i++) {
ll M1 = M[i - ], M2 = M[i];
ll C2 = C[i], C1 = C[i - ];
ll T = gcd(M1, M2); if ((C2 - C1) % T != ) { flag=; 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];
}
if(flag) cout<<C[K]<<endl;
else cout<<-<<endl; }
return ;
}
欧几里得(辗转相除gcd)、扩欧(exgcd)、中国剩余定理(crt)、扩展中国剩余定理(excrt)简要介绍的更多相关文章
- 2020牛客寒假算法基础集训营4 -- A : 欧几里得
A:欧几里得 考察点 : 递推, gcd 坑点 : long long 这道题题解说的十分详细,是裴波那契的一种变形,只不过换成 gcd 了. Code: #include <cstdio> ...
- POJ - 1061 青蛙的约会 (扩展欧几里得求同余式)
题意:两只青蛙在网上相识了,它们聊得很开心,于是觉得很有必要见一面.它们很高兴地发现它们住在同一条纬度线上,于是它们约定各自朝西跳,直到碰面为止.可是它们出发之前忘记了一件很重要的事情,既没有问清楚对 ...
- [poj1061]青蛙的约会<扩展欧几里得>
题目链接:http://poj.org/problem?id=1061 其实欧几里得我一直都知道,只是扩展欧几里得有点蒙,所以写了一道扩展欧几里得裸题. 欧几里得算法就是辗转相除法,求两个数的最大公约 ...
- 【洛谷】【扩欧】P1516 青蛙的约会
[题目描述] 两只青蛙在网上相识了,它们聊得很开心,于是觉得很有必要见一面.它们很高兴地发现它们住在同一条纬度线上,于是它们约定各自朝西跳,直到碰面为止.可是它们出发之前忘记了一件很重要的事情,既没有 ...
- gcd,扩展欧几里得,中国剩余定理
1.gcd: int gcd(int a,int b){ ?a:gcd(b,a%b); } 2.中国剩余定理: 题目:学生A依次给n个整数a[],学生B相应给n个正整数m[]且两两互素,老师提出问题: ...
- hdu 5512 Pagodas 扩展欧几里得推导+GCD
题目链接 题意:开始有a,b两点,之后可以按照a-b,a+b的方法生成[1,n]中没有的点,Yuwgna 为先手, Iaka后手.最后不能再生成点的一方输: (1 <= n <= 2000 ...
- GCD nyoj 1007 (欧拉函数+欧几里得)
GCD nyoj 1007 (欧拉函数+欧几里得) GCD 时间限制:1000 ms | 内存限制:65535 KB 难度:3 描述 The greatest common divisor ...
- gcd模板(欧几里得与扩展欧几里得、拓展欧几里得求逆元)
gcd(欧几里得算法辗转相除法): gcd ( a , b )= d : 即 d = gcd ( a , b ) = gcd ( b , a mod b ):以此式进行递归即可. 之前一直愚蠢地以为辗 ...
- 算法马拉松35 E 数论只会Gcd - 类欧几里得 - Stern-Brocot Tree - 莫比乌斯反演
题目传送门 传送门 这个官方题解除了讲了个结论,感觉啥都没说,不知道是因为我太菜了,还是因为它真的啥都没说. 如果 $x \geqslant y$,显然 gcd(x, y) 只会被调用一次. 否则考虑 ...
随机推荐
- 17..userinfo.txt 文件中存放以下结构:
alex:alex3714 wusir:123456 meet:meet123 1.让用户选择: 1.注册 2.登录 2.用户选择注册就将账号和密码添加到userinfo.txt中,如果用户名存在就提 ...
- 当项目只有src文件和web文件时eclipse如何导入javaweb工程
原理是:利用工具生成class文件,并且在过程中检查出错误,生成对应的编译后文件,这样才能在tomcat等服务器上跑,服务器上只能跑编译后的文件. 1. 2. 3. . 4. 5. 6. 7.
- (十四)SpringBoot开发微信授权支付
前提:配置好域名,在公众号配置 一.引用jar包,在pom.xml文件加入依赖 <dependency> <groupId>com.github.binarywang</ ...
- 如何对接payjs的个人微信扫码支付接口
在众多个人支付接口的产品中,要寻找一个稳定可靠的产品是比较难的,所幸遇到payjs,感觉逼格较高,非常满足自己的品味.推荐大家使用.下边是我在对接payjs的过程中的一些经验和技巧,分享给大家. 一. ...
- C 语言实例 - 字符转 ASCII 码
C 语言实例 - 字符转 ASCII 码 C 语言实例 C 语言实例 ASCII 定义了 个字符. 分类: 一:-.(删除键)是控制字符 二:空白字符:空格(). 制表符. 垂直制表符. 换行. 回车 ...
- Caffe实战五(Caffe可视化方法:编译matlab接口)
接上一篇文章,这里给出配置caffe后编译matlab接口的方法.(参考:<深度学习 21天实战Caffe 第16天 Caffe可视化方法>) 1.将Matlab目录更新至Caffe的Ma ...
- 统计最长回文串(传说中的Manacher算法)Hihocoder 1032
算法的核心就在这一句上了:p[i] = min(p[2*id-i], p[id] + id - i); #include <iostream> #include <cstdio> ...
- 1-27TreeSet简介
使用TreeSet存储Integer对象 TreeSet的特点是可以对存放进去的元素进行排序. package com.monkey1024.set; import java.util.TreeSet ...
- Hive_Hive的管理_远程服务
远程服务启动方式 - 端口号10000 - 启动方式: #hive --service hiveserver & 以JDBC或ODBC的程序登陆到hive中操作数据时,必须选用远程服务启动方式 ...
- C++使用ADO连接数据库及其实例
读写数据库的技术很多,现在多用ADO.ADO以COM方式提供,所以它的很多行为遵循COM规范.首先,要引入ADO的COM文件,它的位置一般在"C:/Program Files/Common ...