数论——扩展欧几里得
No.1 前置知识
-
欧几里得算法(辗转相除法)
-
裴蜀定理
No.2 算法,证明及函数
扩展欧几里得算法用来解决这样一个问题:给定两个非零的整数 \(a\) 和 \(b\),求一组整数解 \((x,y)\) 使得 \(ax+by = gcd(a,b)\) 成立(通过裴蜀定理可知一定存在解)。
证明:
设 \(ax_1+by_1=gcd(a,b)\),设 \(bx_2+(a \bmod b)y_2=gcd(b,a \bmod b)\)
由欧几里得算法可知:\(gcd(a,b)=gcd(b,a \bmod b)\)
\(∴ax_1+by_1=bx_2+(a \bmod b)y_2\)
又\(∵a \bmod b=a-kb(k\) 为商且 \(k \in \mathbb Z)\)
又\(∵k=\lfloor \displaystyle \frac{a}{b} \rfloor\)
\(∴ax_1+by_1=bx_2+(a-b\lfloor \displaystyle \frac{a}{b} \rfloor)y_2\)
整理得:\(ax_1+by_1=ay_2+b(x_2-\lfloor \displaystyle \frac{a}{b} \rfloor y_2)\)
\(∴ \exists x_1=y_2,y_1=x_2-\lfloor \displaystyle \frac{a}{b} \rfloor y_2\)
可以看出:\((x_1,y_1)\) 这组解由 \((x_2,y_2)\) 得来
不难发现:当\(x_n,y_n\) 关于 \(gcd(a,0)\) 时,\(ax_n+by_n=a,\exists x_n=1,y_n=0\)
\(\exists\) 这组边界整数解可得 \(x_1,y_1\)
函数:
Code
void exgcd(int a,int b){
if(b==0){
x=1;
y=0;
return;
}
exgcd(b,a%b);
int t=x;
x=y;
y=t-(a/b)*y;
}
No.3 例题
3.1同余方程
链接:\(Link\)
分析:
题目要求关于 \(x\) 的同余方程 \(a x \equiv 1 \pmod {b}\) 的最小正整数解。
可以转换得到:\(ax \bmod b=1\)
于是 \(ax+by=1\)
这个式子我们很熟悉,但是它有一点不对劲,扩欧的标准是 \(ax+by=gcd(a,b)\),为什么有 \(1\)。
很简单,它说明了 \(gcd(a,b)=1\),\(a,b\)互质。
接下来,就可用扩欧得出 \(x,y\) 的一组特殊解。
问题来了,此时 \(x,y\) 只满足 \(ax+by=1\),\(x\) 不一定为最小整数解。
此时,可将 \(x\) 加上 \(kb(k \in \mathbb Z)\),从而得到 \(x\) 的最小整数解。
\(∵ax+by=1\)
\(∴ax+by+pab-pab=1\)
\(∴a(x-bp)+b(y-ap)=1\)
\(∴\) 可得 \(x\) 的最小整数解为 \((x\bmod b+b)\bmod b\)
Code
#include<bits/stdc++.h>
using namespace std;
long long x,y;
long long read(){
long long s=0,w=1;
char ch=getchar();
while(ch>'9'||ch<'0'){
if(ch=='-'){
w=-1;
}
ch=getchar();
}
while(ch>='0'&&ch<='9'){
s=s*10+ch-'0';
ch=getchar();
}
return s*w;
}
void exgcd(long long a,long long b){
if(b==0){
x=1;
y=0;
return;
}
exgcd(b,a%b);
long long t=x;
x=y;
y=t-(a/b)*y;
}
int main(){
long long a,b;
scanf("%lld%lld",&a,&b);
exgcd(a,b);
printf("%lld\n",(x%b+b)%b);
return 0;
}

浙公网安备 33010602011771号