-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
5c4ec87
commit 75c9faf
Showing
6 changed files
with
187 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,155 @@ | ||
<!DOCTYPE html> | ||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="zh-Hans" lang="zh-Hans"> | ||
<head> | ||
<link href="https://gmpg.org/xfn/11" rel="profile"> | ||
<meta http-equiv="content-type" content="text/html; charset=utf-8"> | ||
<meta name="generator" content="Hugo 0.123.6"> | ||
|
||
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
|
||
<title>辗转相除法和裴蜀定理 · Weily09's Blog</title> | ||
<meta name="description" content="" /> | ||
|
||
|
||
<link type="text/css" rel="stylesheet" href="https://weilycoder.github.io/css/print.css" media="print"> | ||
<link type="text/css" rel="stylesheet" href="https://weilycoder.github.io/css/poole.css"> | ||
<link type="text/css" rel="stylesheet" href="https://weilycoder.github.io/css/syntax.css"> | ||
<link type="text/css" rel="stylesheet" href="https://weilycoder.github.io/css/hyde.css"> | ||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Abril+Fatface|PT+Sans:400,400i,700"> | ||
|
||
|
||
|
||
<link rel="apple-touch-icon-precomposed" sizes="144x144" href="/apple-touch-icon-144-precomposed.png"> | ||
<link rel="shortcut icon" href="/favicon.png"> | ||
|
||
|
||
<script> | ||
MathJax = { | ||
tex: { | ||
inlineMath: [['$', '$'], ['\\(', '\\)']] | ||
} | ||
}; | ||
</script> | ||
<script id="MathJax-script" async | ||
src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"> | ||
</script> | ||
</head> | ||
|
||
<body class=" "> | ||
<aside class="sidebar"> | ||
<div class="container sidebar-sticky"> | ||
<div class="sidebar-about"> | ||
<a href="https://weilycoder.github.io/"><h1>Weily09's Blog</h1></a> | ||
<p class="lead"> | ||
I write, therefore I am. | ||
</p> | ||
</div> | ||
|
||
<nav> | ||
<ul class="sidebar-nav"> | ||
<li><a href="https://weilycoder.github.io/">Home</a> </li> | ||
<li><a href="https://github.com/weilycoder/"> Github </a></li><li><a href="https://www.luogu.com/user/818693/"> Luogu </a></li> | ||
</ul> | ||
</nav> | ||
|
||
<p>© 2024. All rights reserved. </p> | ||
</div> | ||
</aside> | ||
|
||
<main class="content container"> | ||
<div class="post"> | ||
<h1>辗转相除法和裴蜀定理</h1> | ||
<time datetime=2024-06-05T09:04:35+0800 class="post-date">Wed, Jun 5, 2024</time> | ||
<p>数论基础第二弹!</p> | ||
<h2 id="辗转相除法">辗转相除法</h2> | ||
<p>又称欧几里得算法,算法关键在于 | ||
$$\gcd(a,b)=\gcd(b,a\bmod b).$$</p> | ||
<blockquote> | ||
<p>证:不妨设 $a>b,a=qb+r$,则 $r=a\bmod b$,设 $d\mid a,d\mid b$,则 $\dfrac{r}{d}=\dfrac{a}{d}-\dfrac{bk}{d}$。</p> | ||
<p>由上式,$\dfrac{r}{d}$ 为整数,即 $d\mid r$,所以对 $a,b$ 的公约数,也是 $b,r$ 的公约数。</p> | ||
<p>反过来,设 $d\mid b,d\mid r$,则 $\dfrac{a}{d}=\dfrac{r}{d}+\dfrac{bk}{d}$。</p> | ||
<p>显然 $\dfrac{a}{d}$ 是整数,即 $d\mid d$,故 $b,r$ 的公约数也是 $a,b$ 的公约数。</p> | ||
<p>既然公约数相同,那么最大公约数也相同。</p> | ||
</blockquote> | ||
<p>容易写出递归版:</p> | ||
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">int</span> <span style="color:#a6e22e">gcd</span>(<span style="color:#66d9ef">int</span> a, <span style="color:#66d9ef">int</span> b) { <span style="color:#66d9ef">return</span> b<span style="color:#f92672">?</span> gcd(b, a <span style="color:#f92672">%</span> b)<span style="color:#f92672">:</span> a; } | ||
</span></span></code></pre></div><h3 id="时间复杂度">时间复杂度</h3> | ||
<p>欧几里得算法的最坏时间复杂度为 $O(n)$,这里 $n$ 是输入数据在二进制下的长度。换句话说,复杂度是 $O(\log a)$(默认 $a,b$ 同阶)。</p> | ||
<blockquote> | ||
<p>证:</p> | ||
<ul> | ||
<li>$a\lt b$ 时,下一次迭代到 $\gcd(b,a);$</li> | ||
<li>$a\ge b$ 时,下一次迭代到 $\gcd(b,a\bmod b)$,而 $a\bmod b$ 至少让 $a$ 折半,即该过程最多发生 $O(\log a)=O(n)$ 次。</li> | ||
</ul> | ||
<p>情况一发生后一定会发生情况二,故前者发生次数不多于后者发生次数。</p> | ||
<p>因此最多递归 $O(n)$ 次。</p> | ||
</blockquote> | ||
<p>欧几里得算法达到最坏时间复杂度仅当输入数据是斐波那契数列<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>的相邻两项。</p> | ||
<h3 id="更相减损术">更相减损术</h3> | ||
<p>由于取模的时间常数高(尤其在高精运算中不可忽视),我们可以利用加减法代替乘除。</p> | ||
<p>更相减损术的核心是: | ||
$$\gcd(a,b)=\gcd(b,a-b).$$</p> | ||
<p>注意到若 $a\gg b$,时间开销将不可接受,若能进行高效除以 $2$ 的操作(如位运算),可以进行优化。</p> | ||
<p>若 $2\mid a,2\mid b$,则 $\gcd(a,b)=2\gcd\left(\dfrac{a}{2},\dfrac{b}{2}\right);$</p> | ||
<p>不然,若 $2\mid a$($2\mid b$ 同理),$\gcd(a,b)=\gcd\left(\dfrac{a}{2},b\right).$</p> | ||
<p>由于两次操作内 $a,b$ 之一必将减半,时间复杂度为 $O(\log a).$</p> | ||
<h2 id="裴蜀定理和扩展欧几里得算法">裴蜀定理和扩展欧几里得算法</h2> | ||
<blockquote> | ||
<p>设 $a,b$ 是不全为零的整数,对任意整数 $x,y$,满足 $\gcd(a,b)\mid ax+by$,且存在整数 $x,y$,使得 $ax+by=\gcd(a,b).$</p> | ||
</blockquote> | ||
<p>前者显然,后者构造即可,下面进行构造。</p> | ||
<p>不妨设 $a\ge b,\gcd(a,b)=1$,使用归纳法,若 $b=0$,此时 $a=1$,显然有一组解 $x=1,y=0;$</p> | ||
<p>不然,假设我们已知 $(a\bmod b,b)$ 为系数时的一组解 $(x_0,y_0)$,尝试推出 $(a,b)$ 为系数的一组解: | ||
$$\begin{aligned}(a\bmod b)x_0+by_0&=1;\\(a-\left\lfloor\dfrac{a}{b}\right\rfloor b)x_0+by_0&=1;\\ax_0+b(y_0-\left\lfloor\dfrac{a}{b}\right\rfloor x_0)&=1.\end{aligned}$$</p> | ||
<p>故解为 $(x_0,y_0-\left\lfloor\dfrac{a}{b}\right\rfloor x_0)$,由数学归纳法,对任意 $\gcd(a,b)=1$,均能构造 $(x,y)$ 使 $ax+by=1$,进而原命题得证。</p> | ||
<p>容易写出代码:</p> | ||
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">int</span> <span style="color:#a6e22e">exgcd</span>(<span style="color:#66d9ef">int</span> a, <span style="color:#66d9ef">int</span> b, <span style="color:#66d9ef">int</span> <span style="color:#f92672">&</span>x, <span style="color:#66d9ef">int</span> <span style="color:#f92672">&</span>y) { | ||
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">if</span> (<span style="color:#f92672">!</span>b) { | ||
</span></span><span style="display:flex;"><span> x <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>, y <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; | ||
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">return</span> a; | ||
</span></span><span style="display:flex;"><span> } | ||
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">int</span> d <span style="color:#f92672">=</span> exgcd(b, a <span style="color:#f92672">%</span> b, y, x); | ||
</span></span><span style="display:flex;"><span> y <span style="color:#f92672">-=</span> a <span style="color:#f92672">/</span> b <span style="color:#f92672">*</span> x; | ||
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">return</span> d; | ||
</span></span><span style="display:flex;"><span>} | ||
</span></span></code></pre></div><p>由于计算可行解在求最大公因数的过程中,这种算法被称作扩展欧几里得算法。</p> | ||
<p>有时我们担心,扩展欧几里得算法给出的可行解过大,使得发生溢出;幸运的是,可以证明,上述算法给出的解满足 $|x|<b,|y|<a.$</p> | ||
<p>归纳法易证。</p> | ||
<div class="footnotes" role="doc-endnotes"> | ||
<hr> | ||
<ol> | ||
<li id="fn:1"> | ||
<p>斐波那契数列,又称兔子数列,定义如下:$f_0=0,f_1=1,f_n=f_{n-1}+f_{n-2}(n>1).$ <a href="#fnref:1" class="footnote-backref" role="doc-backlink">↩︎</a></p> | ||
</li> | ||
</ol> | ||
</div> | ||
|
||
|
||
<script src="https://giscus.app/client.js" | ||
data-repo="weilycoder/MyBlogDiscussion" | ||
data-repo-id="R_kgDOMElpzw" | ||
data-category="Announcements" | ||
data-category-id="DIC_kwDOMElpz84Cf1wZ" | ||
data-mapping="pathname" | ||
data-strict="1" | ||
data-reactions-enabled="1" | ||
data-emit-metadata="0" | ||
data-input-position="top" | ||
data-theme="light_high_contrast" | ||
data-lang="zh-CN" | ||
data-loading="lazy" | ||
crossorigin="anonymous" | ||
async> | ||
</script> | ||
|
||
</div> | ||
|
||
|
||
</main> | ||
|
||
|
||
|
||
|
||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters