【墨鳌】【数论小结 01】【乘法逆元】【扩展欧几里得】
作者:互联网
数论小结
1. 扩展欧几里得
首先,根据辗转相除法,不难有:
\[\gcd(a,b)=\gcd(b,a\%b) \]关于扩展欧几里得算法,是解决线性方程:\(ax+by=c\) 当且仅当,\(\gcd(a,b)|c\) 有解
又因为,\(x,y\in\Z\),所以问题可以转化为,解线性方程:\(ax+by=\gcd(a,b)\) 这就是扩展欧几里得算法的初始条件
假设,我们有方程的一组解 \(x_0,y_0\), 则:
\[ax_0+by_0=\gcd(a,b)=\gcd(b,a\%b)\qquad(1) \]于是,构造新的线性方程与其解 \(x_1,y_1\),满足:
\[bx_1+(a\%b)y_1=\gcd(b,a\%b)\qquad(2) \]联立 \((1),(2)\) 式,我们有:
\[ax_0+by_0=\gcd(a,b)=\gcd(b,a\%b)=bx_1+(a\%b)y_1\\ =bx_1+(a-\lfloor a/b\rfloor\times b)y_1\\ =ay_1+b(x_1-\lfloor a/b\rfloor y_1) \]结论一:
\[\cases{ x_0\leftarrow y_1\\ y_0\leftarrow x_1-\lfloor a/b\rfloor y_1\\ } \]结论二:
\[\cases{ x_0\leftarrow y_1\\ y_0\leftarrow x_1\\ a\leftarrow b\\ b\leftarrow a\%b\\ \gcd(a,b)\leftarrow \gcd(b,a\%b)\\ } \]于是可以考虑设计递归或者迭代代码。
递归版本
int ex_gcd(int a, int b, int &x, int &y) {
if (b == 0) {
x = 1, y = 0;
return a;
}
int d = ex_gcd(b, a % b, y, x);// 注意:这里已经调换了x,y顺序
y -= (a / b) * x;
return d;
}
2. 乘法逆元(扩展欧几里得算法求解)
问题描述
求解 \(ax\equiv1\mod{n}\)
\[ax\equiv1\mod n\\ \iff ax+ny\equiv1\mod n \]当且仅当,\(\gcd(a,n)=1\) 有解,求解 \(ax+ny=1\) 使用扩展欧几里得算法
乘法逆元-代码
int inv(int a, int n) {
int x, y, d = ex_gcd(a, n, x, y);
if (d == 1) {
if (x % n <= 0)
return x % n + n;
else
return x % n;
}
return -1;
}
标签:01,gcd,leftarrow,int,欧几里得,扩展,逆元,墨鳌,ax 来源: https://www.cnblogs.com/JasonCow/p/16194513.html