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)简要介绍的更多相关文章

  1. 2020牛客寒假算法基础集训营4 -- A : 欧几里得

    A:欧几里得 考察点 : 递推, gcd 坑点 : long long 这道题题解说的十分详细,是裴波那契的一种变形,只不过换成 gcd 了. Code: #include <cstdio> ...

  2. POJ - 1061 青蛙的约会 (扩展欧几里得求同余式)

    题意:两只青蛙在网上相识了,它们聊得很开心,于是觉得很有必要见一面.它们很高兴地发现它们住在同一条纬度线上,于是它们约定各自朝西跳,直到碰面为止.可是它们出发之前忘记了一件很重要的事情,既没有问清楚对 ...

  3. [poj1061]青蛙的约会<扩展欧几里得>

    题目链接:http://poj.org/problem?id=1061 其实欧几里得我一直都知道,只是扩展欧几里得有点蒙,所以写了一道扩展欧几里得裸题. 欧几里得算法就是辗转相除法,求两个数的最大公约 ...

  4. 【洛谷】【扩欧】P1516 青蛙的约会

    [题目描述] 两只青蛙在网上相识了,它们聊得很开心,于是觉得很有必要见一面.它们很高兴地发现它们住在同一条纬度线上,于是它们约定各自朝西跳,直到碰面为止.可是它们出发之前忘记了一件很重要的事情,既没有 ...

  5. gcd,扩展欧几里得,中国剩余定理

    1.gcd: int gcd(int a,int b){ ?a:gcd(b,a%b); } 2.中国剩余定理: 题目:学生A依次给n个整数a[],学生B相应给n个正整数m[]且两两互素,老师提出问题: ...

  6. hdu 5512 Pagodas 扩展欧几里得推导+GCD

    题目链接 题意:开始有a,b两点,之后可以按照a-b,a+b的方法生成[1,n]中没有的点,Yuwgna 为先手, Iaka后手.最后不能再生成点的一方输: (1 <= n <= 2000 ...

  7. GCD nyoj 1007 (欧拉函数+欧几里得)

    GCD  nyoj 1007 (欧拉函数+欧几里得) GCD 时间限制:1000 ms  |  内存限制:65535 KB 难度:3   描述 The greatest common divisor ...

  8. gcd模板(欧几里得与扩展欧几里得、拓展欧几里得求逆元)

    gcd(欧几里得算法辗转相除法): gcd ( a , b )= d : 即 d = gcd ( a , b ) = gcd ( b , a mod b ):以此式进行递归即可. 之前一直愚蠢地以为辗 ...

  9. 算法马拉松35 E 数论只会Gcd - 类欧几里得 - Stern-Brocot Tree - 莫比乌斯反演

    题目传送门 传送门 这个官方题解除了讲了个结论,感觉啥都没说,不知道是因为我太菜了,还是因为它真的啥都没说. 如果 $x \geqslant y$,显然 gcd(x, y) 只会被调用一次. 否则考虑 ...

随机推荐

  1. iOS app支付宝接口调用的一点总结(补充支付宝SDK&Demo下载地址)

    由于app内需要用到支付功能,选择了当前最流行的支付宝进行支付.在进行内嵌支付宝功能开发时,被它狠狠的耍了一把. 根据支付宝开发文档,参考demo代码.将相关支付功能加到了自己的代码中.一些根据文档来 ...

  2. 五粮液【线段树】By cellur925

    题目传送门 考场上感觉的确是线段树,还要维护区间最值...最值怎么维护?还要区间修改?\(update\)的时候加一下就好了吧...之后怎么搞啊?\(qwqwq\)之后好像不太会了...果断删除几乎快 ...

  3. assembly x86(nasm)串比较

    预留字符串口令,输入口令串与预留密码串比较.若匹配则显示“MATCH!CONGRATULATION”,否则显示“NOMATCH!”,并让用户重新输入,程序能对口令进行测试,但测试次数最多3次,若3次输 ...

  4. C#Sqlite增删改查

    说到使用数据库的话,无非也就是对数据的增加,删除和修改以及查询.前文已经 创建好了程序,现在我们就可以来具体实现Sqlite的数据操作,增删改查. 第一步,创建连接字符串来连接数据库: private ...

  5. Csc”任务不支持“SharedCompilationId”参数。请确认该参数存在于此任务中,并且是可设置的公共实例属性

    今天.NetCore2.1版本,建立Asp.net Core web应用程序项目时,报以下错误: 未能使用“Csc”任务的输入参数初始化该任务. “Csc”任务不支持“SharedCompilatio ...

  6. python 对mongdb的简单操作

    准备工作:1.选择安装合适的mongodb到本地电脑,2.创建mongodb实例,3,开启mongodb实例,4,下载pymongo第三方库,5.下载pycharm对mongodb可视化支持的插件mo ...

  7. SNMP消息传输机制

    1.引言 基于TCP/IP的网络管理包含3个组成部分: 1) 一个管理信息库MIB(Management Information Base).管理信息库包含所有代理进程的所有可被查询和修改的参数.RF ...

  8. kibana通过nginx配置访问用户验证

    背景: 现在搭建好了efk,其中kibana是可以在网页上访问的可视化工具,搭建好的kibana默认没有访问控制权限,任何人都能访问,这样存在一些安全隐患和隐私问题.这里我把设置的访问验证过程记录一下 ...

  9. python入门之前面内容拾遗

    int n1 = 123 #根据int类,创建了一个对象 n2 = int(123) #根据int类,创建了一个对象,这里实际上调用了int类里的内置函数__int__(x,2),其中x为定义的对象, ...

  10. linux增加系统监视器的快捷键

    系统命令:gnome-system-monitor 可在终端输入调用 在系统相应的快捷键设置区设置即可