欧几里得算法与 EX

欧几里得算法

欧几里得算法又称辗转相除法,用来求两个数的最大公约数的算法。

省流:\(gcd(a,b)=gcd(b,a\mod b)\)

学习笔记

点击查看代码
#include <bits/stdc++.h>
using namespace std;
int a,b;
int gcd(int x,int y){
	return y==0?x:gcd(y,x%y);
}
int main(){
    cin>>a>>b; 
    cout<<gcd(a,b);
    return 0;
}

拓展欧几里得算法 exgcd

学习笔记

学习笔记

常用于求解 \(ax+by=gcd(a,b)\) 的一组可行解。

接下来就是推例子了:

\[\because gcd(a,b)=gcd(b,a\mod b) \]

\[\therefore ax+by=bx_2+(a \mod b)y_2 \]

\[\because a \mod b=a-b\times \lfloor \frac{a}{b} \rfloor \]

\[\therefore ax+by=bx_2+( a-b\times \lfloor \frac{a}{b} \rfloor )y_2 \]

\[\therefore ax+by=bx_2+ay_2-by_2\lfloor \frac{a}{b} \rfloor \]

\[\therefore ax+by=ay_2+b(x_2-y_2\lfloor \frac{a}{b} \rfloor) \]

然后我们就发现 \(x=y_2,y=x_2-y_2\lfloor \frac{a}{b} \rfloor\)

\(x_2,y_2\) 又可以从 \(x_3,y_3\) 推过来。

我们就需要不断做欧几里得法,当 \(a=gcd(a,b),b=0\) 时,我们这时取 \(x_n=1,y_n=0\),因为 \(b=0\) 所以 \(y_n\) 取任何数都没问题,但取 \(0\) 的时候 \(x\)\(y\) 增长速度更慢一些,还有注意解可能为负数的情况,所以要取模变正数。

点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define ll long long
void exgcd(ll a,ll b,ll &x,ll &y){
	if(b==0){
		x=1,y=0;
		return;
	}
	exgcd(b,a%b,y,x);
	y-=a/b*x;
}
int main(){
	ios::sync_with_stdio(false);
	ll a,b;
	cin>>a>>b;
	ll d=__gcd(a,b);
	if(b%d!=0){
		cout<<"impossible\n";
	}
	else{
		ll x,y;
		exgcd(a,b,x,y);
		x=(x*(b/d)%b+b)%b;//注意这要调整解
		cout<<x<<"\n";
	}
    return 0;
}
posted @ 2024-09-23 20:24  sad_lin  阅读(5)  评论(0编辑  收藏  举报