Loading

数论——扩展欧几里得

No.1 前置知识

  1. 欧几里得算法(辗转相除法)

  2. 裴蜀定理


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;
}

认真学数学\(ing\)

完结

posted @ 2022-09-03 12:01  faith_xy  阅读(63)  评论(0)    收藏  举报