gcd欧几里德算法/extgcd扩展欧几里德算法以及在解不定方程中的应用
2017-03-19 21:10
288 查看
这个应该是我在noip前就应该会的东西 ,但是当时也许只是记下了代码吧 ,现在有诸多的不理解。后来借着书和几篇博客弄懂了并小证了一下,鉴于网上有些博客关于这个的写的真的不好看,所以自己来总结一下,顺带以后也能看。
顺带一提,gcd(a,b)表示a,b的最大公约数。
既然是辗转相除法,自然就是%%%,%到互相整除为止。代码也很详尽简洁。
最小公倍数为两数之积除以他们的最大公约数,相信大家都能明白。
给定一个形如方程ax+by=d,求它的整数解。
我们知道a,b为整数,d是整数,使得x,y为整数解,那么需要约掉系数中相同的部分,于是方程ax+by=d有整数解⇒gcd(a,b)|d
所以说,假设我们有d=gcd(a,b)∗t,则方程ax+by=d的解为agcd(a,b)x+bgcd(a.b)y=gcd(a,b)的t倍,那么原问题转化为求方程agcd(a,b)x+bgcd(a.b)y=gcd(a,b)的解了。
再推到一般,若a,b互质,有ax+by=1有解。
然后接下来我们考虑特殊解的情况:
gcd(a,b)递归的最终结果为gcd(k,0),假定方程有解,那么最终有a∗1+b∗0=gcd(a,b),即a∗1+b∗0=1,即x=1, y=0出现,这是在求gcd时递归形成的。若我们也这样地求解方程呢?
于是我们来找ax+by=gcd(a,b)与bx′+(a%b)∗y′=gcd(b,a%b)的关系,由于a%b=a−(a/b)∗b(整数除法) 所以代入有ay′+b(x′−a/b∗y′)=gcd(a,b)=gcd(b,a%b)
于是原方程解为x=y′,y=x′−(a/b)∗y′。
这样我们就能递归地计算方程的解了。
不定方程不是有很多解吗?是的,这只是最小解。设最小解为x0,y0,它的所有解为x=x0+bgcd(a,b)和y=y0+agcd(a,b)。(自己带到方程里展开就有恒等式,这里不证了)当gcd(a,b)=1时,有x=x0+b,y=y0+a。
例题:zoj3609求逆元
方法同上,AC代码
关于逆元,请移步逆元-wiki
谢谢看到这里
顺带一提,gcd(a,b)表示a,b的最大公约数。
欧几里德算法
辗转相除法求最大公约数问题,同可求最小公倍数。既然是辗转相除法,自然就是%%%,%到互相整除为止。代码也很详尽简洁。
int regulargcd(int x,int y) { return y==0?x:(regulargcd(y,x%y)); }
最小公倍数为两数之积除以他们的最大公约数,相信大家都能明白。
扩展欧几里德算法
我之前一直困惑的是它为什么可以求不定方程的解,后来基本明白了:给定一个形如方程ax+by=d,求它的整数解。
我们知道a,b为整数,d是整数,使得x,y为整数解,那么需要约掉系数中相同的部分,于是方程ax+by=d有整数解⇒gcd(a,b)|d
所以说,假设我们有d=gcd(a,b)∗t,则方程ax+by=d的解为agcd(a,b)x+bgcd(a.b)y=gcd(a,b)的t倍,那么原问题转化为求方程agcd(a,b)x+bgcd(a.b)y=gcd(a,b)的解了。
再推到一般,若a,b互质,有ax+by=1有解。
然后接下来我们考虑特殊解的情况:
gcd(a,b)递归的最终结果为gcd(k,0),假定方程有解,那么最终有a∗1+b∗0=gcd(a,b),即a∗1+b∗0=1,即x=1, y=0出现,这是在求gcd时递归形成的。若我们也这样地求解方程呢?
于是我们来找ax+by=gcd(a,b)与bx′+(a%b)∗y′=gcd(b,a%b)的关系,由于a%b=a−(a/b)∗b(整数除法) 所以代入有ay′+b(x′−a/b∗y′)=gcd(a,b)=gcd(b,a%b)
于是原方程解为x=y′,y=x′−(a/b)∗y′。
这样我们就能递归地计算方程的解了。
int extgcd(int a,int b,int &x,int &y) { if(b==0) { x=1; y=0; return a; } else { int ans; ans=extgcd(b,a%b,x,y); int tmp=x; x=y; y=tmp-(a/b)*y; return ans; } }
不定方程不是有很多解吗?是的,这只是最小解。设最小解为x0,y0,它的所有解为x=x0+bgcd(a,b)和y=y0+agcd(a,b)。(自己带到方程里展开就有恒等式,这里不证了)当gcd(a,b)=1时,有x=x0+b,y=y0+a。
while(x<=0) { x+=(b/res); } printf("%d\n",x);
例题:zoj3609求逆元
方法同上,AC代码
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
//zoj3609 AC
using namespace std;
int extgcd(int a,int b,int &x,int &y) { if(b==0) { x=1; y=0; return a; } else { int ans; ans=extgcd(b,a%b,x,y); int tmp=x; x=y; y=tmp-(a/b)*y; return ans; } }
int regulargcd(int x,int y) { return y==0?x:(regulargcd(y,x%y)); }
int main()
{
int a,b;
int cas;
scanf("%d",&cas);
for(int z=0;z<cas;z++)
{
scanf("%d%d",&a,&b);
int x,y;
if(regulargcd(a,b)==1)
{
int res=extgcd(a,b,x,y);
if(x>0)
{
printf("%d\n",x);
}
else
{
while(x<=0)
{
x+=(b/res);
}
printf("%d\n",x);
}
}
else
{
printf("Not Exist\n");
}
}
return 0;
}
关于逆元,请移步逆元-wiki
谢谢看到这里
相关文章推荐
- IOCP以及扩展Windows socket函数应用示例
- 欧几里得算法扩展(extended gcd)--解不定方程_初入门
- 扩展欧几里德算法求不定方程
- gcd以及扩展gcd详解
- 扩展gcd求解二元不定方程及其证明
- 扩展的欧几里德算法(Extended_Euclid_gcd)
- hdu_1222_欧几里得_gcd简单应用_欧几里得扩展性质
- POJ 2115 C Looooops 扩展gcd的应用 及其 gcd exgcd的讲解
- 扩展欧几里德算法、证明及其应用
- JS进阶篇--IE浏览器的ActiveXObject对象以及FileSystemobject的应用扩展(完成)
- ?通配符 以及扩展通配符在范型中的应用。。。。。。。。。。。。。。。。。。
- IOCP以及扩展Windows socket函数应用示例
- PHP扩展开发与内核应用阅读笔记---php的作用域以及如何在扩展中定义,查找php变量
- 关于扩展运算符中i++和++i,以及基本类型和引用类型的综合应用
- POJ1061——青蛙的约会(扩展GCD应用)
- 欧几里德算法的扩展-求解不定方程
- Firefox的功能介绍以及扩展的应用
- 欧几里德算法的扩展-求解不定方程
- 使用express.js框架一步步实现基本应用以及构建可扩展的web应用
- 前端打包成桌面应用、以及chrome扩展