拡張ユークリッドアルゴリズム、最小の正の整数解、および乗法逆元について話します

ユークリッド:

まず、ユークリッドの互除法を明確にする必要があります。これは、トスと分割の方法と呼ばれます。
2つの数a、bの最大公約数gcd(a、b)を見つけることです

ll gcd(ll a,ll b)    //欧几里得算法 
{
    
                        //辗转相除法 
	if(a%b==0) return b;
	return gcd(b,a%b);
}

拡張ユークリッドアルゴリズム

一般的に言えば、2進線形方程式Ax + By = gcd(A、B)の(x、y)のすべての解を見つけることです。(AとBが既知であると仮定)
私たちの方法は、この一連の方程式の特別な解を通して彼の一般的な解を取得することです。
次に、2つの質問があり
ます。1。彼の特別な解決策を得る方法は?
2.特別なソリューションから一般的なソリューションを取得するにはどうすればよいですか?****

1.特別な解決策を見つける

ユークリッドのアルゴリズムから、gcd(A、B)はgcd(B、A%B)と書くことができます。
新しい方程式を取得する

Bx2 +(A%B)* y2 = gcd(B、A%B); ------------- 1

A%B = A-(A / B)* B;
方程式をもう一度書き直します

Bx2 + [A-(A / B)* B] y2 = gcd(B、A%B); * ------------ 2

gcd(B、A%B)がA%B = 0になるまで書き留め
られた
とき、式1によってBx2 = Bが得られました。
今回は、式x2 = 1、y2 = 0の特殊な解のグループに到達しました。 ;
この時点で、最初の問題を解決して、連立方程式の特別な解を見つけました。

2.特別なソリューションから一般的なソリューションを取得する方法
式2を引き続き観察します。これで、特別なソリューションx2とy2が得られました。次に、x2とxの関係、およびy2とyの関係がわかれば、一般的な解(x、y)を得ることができます。

次に、式2を整理して次のようにします。

Ay2 + B * [x2-(A / B)* y2] = gcd

元の式はAx + By = gcdです。
このとき、一般解と特別解の関係を得ることができます。

x = y2;
y = x2-(A / B)* y2

特別な解決策を探すプロセスは段階的に繰り返されるため、一般的な解決策を探すプロセスは遡及的なプロセスです。
3x + 5y = 1の例を見てみましょう


ここで(2、-1)は、方程式3x + 5y = 1の解のセットです
**要約:一般解を見つけるプロセスでは、主に、一般解と上記で取得した特別解との関係を使用します。各ステップのAとBの係数が異なるため、特別なソリューションから一般的なソリューションに段階的に戻る必要があります。

Euclid
#include
#
include
include includeを展開します
using namespace std;
const int N=1e6+10;
typedef long long ll;
typedef unsigned long long ull;
ll exgcd(ll a,ll b,ll &x,ll &y) {
if(b==0) {
x=1;
y=0;
return a;
}
ll res= exgcd(b,a%b,x,y);
ll t;
t=x;
x=y;
y=t-a/b*y;
return res;
}
int main() {
ll a,b,x,y;
cin>>a>>b;
ll anss = exgcd(a,b,x,y);
cout<<anss<<" “<<x<<” "<<y;
return 0;
}

別の質問を考えてみましょう:
一連の一般的なソリューションから複数のソリューションを取得する方法は?

方程式
ax + by = gcdが確立されるようにするには、x、yの値が増減する必要があります。a
、bの最小公約数は(a * b)/ gcd(a、 b)、
x = x + b / gcd(a、b)の場合、y = ya / gcd(a、b)の場合、元の式を代入し
て*(x + b / gcd(a、b))+取得ます。 b *(ya / gcd(a、b)))
xまたはyの値がa、bの最小公約数だけ増加または減少するたびに、元の式の値が変更されないことを確認するのは難しくありません。 。
次に、xまたはyの最小変化期間をb / gcd(a、b)またはa / gcd(a、b)
にすることができます。さらに、Ax + By = Cであるかどうかを判断するのは難しくありませんC%gcd(A、B)!= 0の場合、連立方程式には解がないはずです。

これから、最小の正の整数解を導き出します
**

最小の正の整数解

**
拓展欧几里得主要应用于求解方程的解
ax≡b(mod)l
ax-ly=b;
由上面拓展欧几里得算法我们可以求出x,但是x可能为负数,或者x并不是一个最小的正整数解
我们得到了x的周期,在该式子中周期T=l/gcd(a,l);
我们可以选择这样一种处理方式
x=((x%T)+T)%T;
保证x为最小正整数解

乘法逆元

在一个模系p中只有包含[1,p-1]的所有整数,所以在模系p中计算除法的时候由于无法整除出现精度问题,所以我们引入乘法逆元
ax≡1(mod)p
这时x为在模系p中a的逆元
学习完拓展欧几里得后
转化一下
ax-pk=1
a的逆元x的存在条件为gcd(a,p)=1
同样用拓展欧几里得的代码可以求出a的逆元x;

**拓展欧几里得,乘法逆元,最小整数解**
#include <iostream>
#include <cstring>
#include <algorithm>
#include<map>
using namespace std;
const int N=1e6+10;
typedef long long ll;
typedef unsigned long long ull;
l 
ll exgcd(ll a,ll b,ll &x,ll &y) {
    
    
	if(b==0) {
    
    
		x=1;
		y=0;
		return a;
	}
	ll res=	exgcd(b,a%b,x,y);
	ll t;
	t=x;
	x=y;
	y=t-a/b*y;
	return res;
}
int main() {
    
    
	// ax-pk=1
	//p =1000000007
	ll a,b,x,y;
	cin>>a>>b;
	exgcd(a,b,x,y);
	ll ans=exgcd(a,b,x,y);
// ax+by=c
x=x*c/gcd(a,b);
	ll t=b/ans;
	x=(x%t+t)%t;
	cout<<x;
	return 0;
}

欢迎指正

おすすめ

転載: blog.csdn.net/wmy0536/article/details/103984653