【数论】非递归扩展欧几里得定理/Exgcd
2024-8-19 ·最后更新时间:2024-8-20
- 发现有纯迭代法扩展欧几里得定理没有讲 2024-8-20
本篇适用于像扩展Exgcd非递归版和OIwiki看不懂的同学,写这些也是因为Oiwiki上的太晦涩难懂了。
\(\Large\mathcal{1,Matrix representation}\)
首先我们我们们知道 \(a \mod b\) 就相当于 \(a-\lfloor\frac{a}{b}\rfloor b\) 这是很基础的东西不多赘述,同时也根据欧几里得定理可知 \(\gcd(a,b)=\gcd(b,a \mod b)=\gcd(b,a-\lfloor\frac{a}{b}\rfloor b)\) 于是我们由此产生了思考如果,换一种方式表达\(\gcd(b,a \mod b)=\gcd(b,a-\lfloor\frac{a}{b}\rfloor b)\) 会发生什么呢?
我们不妨向矩阵的方向想一想,我们先把 \(b\) 和 \(a \mod b\) 放到向量一个 \(R^2\) 的向量中:
那么根据我们原来对 \(a \mod b\) 的分析他是不是变成了:
等等?如果我们给他变成 \(2*2\) 的矩阵好像有一些奇妙的发现
欸?这个矩阵的每一列上都有相同的元素 \(a\) 或 \(b\) 所以,我们是不是可以把 \(a,b\) 单独提出来放到一个 \(R^2\) 的向量上?答案是可以的所以我们来转化一下,可以得到一个等式:
那么,假设我们当前的矩阵就是最终矩阵 \(\left[\begin{matrix}\gcd(a,b) \\0 \\\end{matrix}\right]\) 那么我们一直将形如上面等式的式子一直迭代最后会得到一个奇妙~~的式子:
那么接下如果我们括号中的矩阵的乘积表示成一个独立的矩阵像:
那么
令
那么
那么 \(x1,x2\) 就是我们的解了,接下来为了方便我们从 \(a,b\) 开始向下迭代,只需要把过程反过来即可所以细节就看代码吧:
int exgcd(int a, int b, int &x, int &y) {
int x1 = 1, x2 = 0, x3 = 0, x4 = 1;
while (b != 0) {
int c = a / b;
std::tie(x1, x2, x3, x4, a, b) =
std::make_tuple(x3, x4, x1 - x3 * c, x2 - x4 * c, b, a - b * c);
}
x = x1, y = x2;
return a;
}
\(\Large\mathcal{2,Iteration method}\)
接下来在来说说纯迭代法吧,OIwiki 上直接丢了一个方程然后让小朋友(作者)自己去推真的是太丧心病狂了,所以我发现了一个更好理解的方法来解析纯迭代法没错还是用矩阵 ,首先我们先不要管 OIwiki 有多丧心病狂,我们从他的式子开始分析也就是:
emmm 有点难入手,我们不妨从一个例子开始?比如 \(a=25,b=7\)
那么过程就应该是:
\(
\begin{cases}
1\cdot 25+0\cdot 7=25\\
0\cdot 25+1\cdot 7=7
\end{cases}
⇒
\begin{cases}
0\cdot 25+1\cdot 7=7\\
1\cdot 25+(-3)\cdot 7=4
\end{cases}
⇒
\begin{cases}
1\cdot 25+(-3)\cdot 7=4\\
(-1)\cdot 25+4\cdot 7=3
\end{cases}
⇒
\begin{cases}\
(-1)\cdot 25+4\cdot 7=3\\
2\cdot 25+(-7)\cdot 7=1
\end{cases}
⇒
\begin{cases}\
2\cdot 25+(-7)\cdot 7=1\\
(-7)\cdot 25+25\cdot 7=0
\end{cases}
\)
如果我们观察等式右边的数字会发现他和欧几里得定理的运行顺序一模一样,所以我们可以尝试运用这一点对方程组做一些小改动。
我们知道所有方程组都可以表示为增广矩阵的形式,那么我们给他转换一下:
如果再给他行变换一下呢?将 \(r2\) 与 \(r1\) 交换,然后将 \(r2-\frac{a}{b}r1\) :
好,现在我们发现当第 \(2\) 行第 \(3\) 列的数为 \(0\) 时 \(x',y'\) 即为满足条件的答案。
所以我们成功的得到了代码:
x = 1, y = 0;
int x1 = 0, y1 = 1, a1 = a, b1 = b;
while (b1) {
int q = a1 / b1;
tie(x, x1) = make_tuple(x1, x - q * x1);
tie(y, y1) = make_tuple(y1, y - q * y1);
tie(a1, b1) = make_tuple(b1, a1 - q * b1);
}
return a1;
安利一下我的博客qwq

浙公网安备 33010602011771号