数论初步?
更新:之前整除的符号写反了……(手动慌张分析)
这种算法及能解决的问题在高中课本《初等数论初步》就有,写这篇博客是希望初中生能看懂。
前置技能:\(a\Leftrightarrow b\)意思是a当且仅当b。简单来说若\(a\Leftrightarrow b\),则一定满足①\(a\)成立时\(b\)一定成立;②\(b\)成立时\(a\)一定成立;③\(a\)不成立时\(b\)一定不成立;④\(b\)不成立时\(a\)一定不成立。
\(a\equiv b\pmod c\)是同余符号,意思是\(a\bmod c=b\bmod c\)。
整除符号:\(a\mid b\Leftrightarrow b\bmod a=0\)。
〇、辗转相除法
众所周知,求两个正整数的最大公约数可以通过以下式子来递归求解。
\(\gcd(a,b)=\begin{cases}b & a\mid b \\ \gcd(b,a\bmod b) & a\not\mid b\end{cases}\)
然而很多人不知道为什么 \(\gcd(a,b)=\gcd(b,a\bmod b)\;(a\not\mid b)\) 是对的。下面给出证明。
证明 设\(c = a\bmod b, a ÷ b = k\cdots\cdots c, \gcd(a,b) = p, \gcd(b, a\bmod b) = q\) 。
$∵a\mid p, ∴ka\mid p, $ 又 \(∵b\mid p, ∴\)
一、扩展欧几里得算法
模板 已知\(a, b(a≥b)\),求不定方程\(ax+by=\gcd(a,b)\)的任意一组整数解。
定理1 \(ax+by=\gcd(a,b)\)必有整数解。
证明 下面给出一种递归的求解方式。当\(a\mid b\)时,\(\gcd(a,b)=a\),原式化为\(ax+by=a\),移项得\(a(x-1)+by=0\),显然有一组解为\(\begin{cases}x=1\\y=0\end{cases}\)(反正我们只要一组解)。
当\(a\not\mid b\)时,\(\gcd(a,b)=\gcd(b,a\bmod b)\)。若\(ax+by=\gcd(a,b)\)有整数解,根据归纳法,则\(bx+(a\bmod b)y=\gcd(b,a\bmod b)\)也有整数解。(此处难懂,请反复推敲)
设\(ax+by=\gcd(a,b)\)的一组解为\(\begin{cases}x=x_1\\y=y_1\end{cases}\),\(bx+(a\bmod b)y=\gcd(b,a\bmod b)\)的一组解为\(\begin{cases}x=x_2\\y=y_2\end{cases}\),则$$\begin{matrix}
ax_1+by_1 & = & \gcd(a,b) \
& & || \
bx_2+(a\bmod b)y_2 & = & \gcd(b,a\bmod b) \
\end{matrix}$$$$\begin{align}
∴ax_1+by_1&=bx_2+(a\bmod b)y_2\
\text{又}∵a\bmod b&=a-\left\lfloor\frac{a}{b}\right\rfloorb\
∴ax_1+by_1&=bx_2+(a-\left\lfloor\frac{a}{b}\right\rfloorb)y_2\
\text{整理得}ax_1+by_1&=ay_2+b(x_2-\left\lfloor\frac{a}{b}\right\rfloory_2)\end{align}$$$$∴\begin{cases}x_1=y_2\y_1=x_2-\left\lfloor\cfrac{a}{b}\right\rfloory_2\end{cases}$$
将结果层层回溯即可。
void exgcd(int a, int &x, int b, int &y) {
if (a % b == 0) {
x = 1; y = 0;
} else {
exgcd(b, y, a%b, x);
y -= a / b * x;
}
}
二、求解形如\(ax+by=c\)的不定方程的整数解
例1 已知\(a, b, c(a≥b)\),求不定方程\(ax+by=c\)的任意一组整数解。
定理2 \(c\mid\gcd(a,b)\Leftrightarrow ax+by=c\)一定有整数解。
证明 根据定理1,\(ax+by=\gcd(a,b)\)一定有整数解,设其中一组解为\(\begin{cases}x=x_1\\y=y_1\end{cases}\)。将解代入原式得\(ax_1+by_1=\gcd(a,b)\)。
又设\(a'=\cfrac{a}{\gcd(a,b)}, b'=\cfrac{b}{\gcd(a,b)}\)(后面的证明还会用到),\(∵a\mid\gcd(a,b),\)\(b\mid\gcd(a,b),\)\(∴a',b'\in\Bbb{Z}\)。
方程两边同除以\(\gcd(a,b)\),得\(a'x+b'y=\cfrac{c}{\gcd(a,b)}\),易发现方程左边为整数,∴当方程右边不为整数(而是小数)时,原方程无解。即当\(c\not\mid\gcd(a,b)\)时,原方程无解。
而当\(c\mid\gcd(a,b)\)时,在第一段证明中的方程\(ax_1+by_1=\gcd(a,b)\)两边同乘\(\cfrac{c}{\gcd(a,b)}\),得\(\cfrac{ac}{\gcd(a,b)}x+\cfrac{bc}{\gcd(a,b)}y=c\),∴可得一组整数解\(\begin{cases}x=\frac{c}{\gcd(a,b)}x_1\\y=\frac{c}{\gcd(a,b)}y_1\end{cases}\)
int gcd(int a, int b) {
return a % b ? gcd(b, a % b) : b;
}
int main() {
/*输入*/
int gcd_ab = gcd(a,b);
if (c % gcd_ab == 0) {
exgcd(a, x, b, y);
x *= c / gcd_ab;
y *= c / gcd_ab;
printf("%d %d\n", x, y);
} else
printf("No Solution\n");
return 0;
}
NeXT. 如果要求不定方程的所有整数解呢?
定理3 若不定方程的一组整数解为\(\begin{cases}x=x_1\\y=y_1\end{cases}\),则它的任意一组整数解都可以表示为\(\begin{cases}x=x_1+kb’\\y=y_1-ka'\end{cases}\)。
证明 设除了已知的一组整数解\(\begin{cases}x=x_1\\y=y_1\end{cases}\)之外,原式的另一个整数解为\(\begin{cases}x=x_2\\y=y_2\end{cases}\)。显然\(ax_1+by_1=ax_2+by_2\),\(∴a(x_2-x_1)=b(y_1-y_2)\)。方程两边同除以\(\gcd(a,b)\),得\(a'(x_2-x_1)=b'(y_1-y_2)\)。两边再同除以\(b'\),得\(\cfrac{a'(x_2-x_1)}{b'}=y_1-y_2\)。显然右边是整数,∴左边是整数。又$∵\gcd(a,b)=1, $ $∴a'\mid b', $ \(∴x_2-x_1\mid b',\) \(∴x_2-x_1=kb'\)即\(x_2=x_1+kb'\)。同理可得\(y_2=y_1-ka'\)。
当然,不会真有这么智障的问题(因为不可能全部输出),而是会问大于/不小于/小于/不大于某个范围的最小/大值。
例2 已知\(a, b, c(a≥b)\),求\(\displaystyle\min_{ax+by=c,x\in\Bbb{Z^*}}x\)。
定理4 若\(c|gcd(a,b)\),则不定方程\(ax+by=c\)在\(x=[0,b'-1]\)间一定有唯一解。
证明 根据定理3,
(TODO)乘法逆元、欧拉函数