扩展欧几里得算法

扩展欧几里得算法

引入

日常生活中我们会遇到一些不定方程,注意本文中所考虑的解都是整数解,如:

\[3x+y=5 \]

我们可以知道这个方程有解,如:

\[\begin{cases}x=1\\y=2\end{cases},\begin{cases}x=2\\y=-1\end{cases},\begin{cases}x=3\\y=-4\end{cases}......\begin{cases}x=1+k\\y=2-3k\end{cases} \]

我们可以知道这个方程有无数的整数解。

算法

我们的扩欧就是来解决形如:

\[ax+by=\gcd(a,b) \]

这一类 \(x,y\) 整数解的求解问题的。

我们可以知道 \(\gcd(a,b)=\gcd(b,a\%b)\)。所以我们在设一个方程:

\[bx'+(a\%b)y'=\gcd(b,a\%b) \]

所以我们有:

\[ax+by=bx'+(a\%b)y' \]

\[ax+by=bx'+(a-\lfloor\frac{a}{b}\rfloor\cdot b)y' \]

\[ax+by=ay'+b\cdot(x'-\lfloor\frac{a}{b}\rfloor\cdot y') \]

所以 \(x=y',y=x'-\lfloor\frac{a}{b}\rfloor\cdot y'\)

递归求解即可:

#pragma GCC optimize("Ofast","-funroll-loops","-fdelete-null-pointer-checks")
#pragma GCC target("ssse3","sse3","sse2","sse","avx2","avx")
#include<bits/stdc++.h>
#define int long long
using namespace std;

int read() {
	char ch=getchar();
	int f=1,x=0;
	while(ch<'0'||ch>'9') {
		if(ch=='-')
			f=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9') {
		x=x*10+ch-'0';
		ch=getchar();
	}
	return f*x;
}

int a,b,x,y;

void exgcd(int a,int b,int &x,int &y) {
    if(b==0) {
        x=1,y=0;
        return ;
    }
    exgcd(b,a%b,x,y);
    int xx=y;
    int yy=x-a/b*y;
    x=xx;
    y=yy;
}

signed main() {
    a=read();b=read();

    exgcd(a,b,x,y);

    cout<<x<<" "<<y<<endl;

	return 0;
}

posted @ 2020-07-29 19:32  huayucaiji  阅读(146)  评论(1编辑  收藏  举报