欧几里得(辗转相除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) 只会被调用一次. 否则考虑 ...
随机推荐
- 洛谷P2505 [HAOI2012]道路(最短路计数)
传送门 早上模拟赛考这题,结果竟然看错题目了orz 然后下午看完题解自己做的时候空间开小了白WA了好久orz 首先,如果以$S$为起点,一条边$(u,v)$在最短路上,则$dis[u]+edge[i] ...
- 修改jq weui自定义对话框点击确定按钮不关闭对话框
如果我们在对话框给用户输入值时,当用户输入空值点击确定按钮时,应该给个提示然后让用户继续输入. 如果在方法里使用 return false;,结果用户输入空值时对话框还是会关闭.正确做法如下: 先设置 ...
- centos 7.3 安装vmtools,解决无法编译共享文件夹模块
环境说明: vmware 12.5.0 build-4352439 centos 7.3.1611 64位,内核版本:Linux version 3.10.0-514.16.1.el7.x86_6 ...
- Python爬虫|爬取喜马拉雅音频
"GOOD Python爬虫|爬取喜马拉雅音频 喜马拉雅是知名的专业的音频分享平台,用户规模突破4.8亿,汇集了有声小说,有声读物,儿童睡前故事,相声小品等数亿条音频,成为国内发展最快.规模 ...
- 解读ping -n 4 127.1 >nul 2>nul
命令解读 ping是Windows.Unix和Linux系统下的一个命令.ping也属于一个通信协议,是TCP/IP协议的一部分.利用"ping"命令可以检查网络是否连通,可以很好 ...
- nginx 一些配置
worker_processes 4; #工作进程数 events { #epoll是多路复用IO(I/O Multiplexing)中的一种方式, #仅用于linux2.6以上内核,可以大大提高ng ...
- Gym - 101810B ACM International Collegiate Programming Contest (2018)
bryce1010模板 http://codeforces.com/gym/101810 #include <bits/stdc++.h> using namespace std; #de ...
- 106 Construct Binary Tree from Inorder and Postorder Traversal 从中序与后序遍历序列构造二叉树
给定一棵树的中序遍历与后序遍历,依据此构造二叉树.注意:你可以假设树中没有重复的元素.例如,给出中序遍历 = [9,3,15,20,7]后序遍历 = [9,15,7,20,3]返回如下的二叉树: ...
- python采用sqlachmy购物商城
一.流程图: 二.目录结构: C:\USERS\DAISY\PYCHARMPROJECTS\S12\MARKET │ __init__.py │ __init__.pyc │ ├─backend │ ...
- TI德州芯片TLV系列和TPS系列芯片区别(转)
TLV和TPS一般会有pin to pin的对应型号: 一般来讲,TPS精度.准确度和性能会好一些,所以价钱要贵一些: 对应TLV就是一样可以实现上述功能,但是精度和性能等级是稍微低一点的: 具体选择 ...