欧几里得算法:最大公因数\((gcd)\)
该算法基于:
\(gcd(a,b)=gcd(b,a\)%\(b)\)
证明:
令\(a\) % \(b = r\),
则 \(a = k * b + r,\)
因此\(r = a - k * b\)
设\(d\)为\(a,b\)的公约数,那么\(d|a, d|b,\)
则\(a - k * b\) 能被\(d\)整除,即\(d|r\),即\(d|(a\) % \(b)\),
因此\(d\)是\(b\) 和 \((a\) %\(b)\)的公约数,
因此\(a,b\) 的公约数和\(b, (a\)%\(b)\)的公约数是同一个数,
得出\(gcd(a,b)=gcd(b,a\)%\(b)\)
同时知道\(gcd(a,0)=a\)
因此递归求解即可:
inline int gcd(int a,int b)
{
if (b==0) return a;
return gcd(b,a%b);
}
对于这个简单的gcd,背结论不求甚解我觉得是可以dei
扩展欧几里得算法\((exgcd)\)
对于一类形如\(ax+by=gcd(a,b)\)的方程求解其x,y的一组解:
通过辗转法,可得\(bx+y(a\)%\(b)=gcd(b,a\)%\(b)\)
用除法代替取模,则:\(bx+y(a-[a/b]*b)=gcd(b,a\)%\(b)\)(这一步仅仅是原方程的变形)
根据上述欧几里得算法可得,\(gcd(a,b)=gcd(b,a\)%\(b)\)
因此\(ax+by=bx‘+y‘(a-[a/b]*b)\)
通过乘法分配律和结合律的运算可得:\[ax+by=ay‘+b(x‘-[a/b]*y‘)\]
其中,\(x‘\)和\(y‘\)是方程\(bx+y(a-[a/b]*b)=gcd(b,a\%b)\)的解,用来借助这个已经求得的x‘和y‘结合已知的a和b推得现在的解\(x,y.\)其中\(a\)和\(b\)不变。我们可以通过递归来求。
递归的边界:
\(ax+by=gcd(a,0)\)时,即\(b=0\)时,\(x=1\ y=0\).显而易见。
故代码很好理解了吧:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int x,y;
int exgcd(int a,int b)
{
if (b==0)
{
x=1;
y=0;
return a;
}
int n=exgcd(b,a%b);
int t=x;
x=y;
y=t-a/b*y;
return n;
}
int main(void)
{
int a,b;
cin>>a>>b;
cout<<exgcd(a,b)<<endl;//这里输出最大公约数
cout<<x<<‘ ‘<<y<<endl;//这个输出方程ax+by=gcd(a,b)的解
return 0;
}
<\font>
原文地址:https://www.cnblogs.com/pigzhouyb/p/10119692.html