【問題解決法】Luogu P1082 [NOIP2012]合同方程式(拡張ユークリッドアルゴリズムの詳細説明)

移動:自分のブログ

トピック

Luogu P1082合同式

回答

gcd(a、b)をa、bの最大公約数として定義します。

ユークリッドの定理によれば、

特に:gcd(a、0)= a

ペイシュウの定理から:

拡張ユークリッドアルゴリズム:a * x + b * y = gcd(a、b)

1. b = 0、gcd(a、b)= aの場合、解はx = 1、y = 0です。

2.b!= 0、仮に 

同等に次のように変換できます。

方程式a * x + b * y = gcd(a、b)と比較すると、x = y '、y = x'-(a / b)* y 'が得られ、操作を繰り返し、x、yを再帰的に変更して、特別なソリューションx0、y0のセットを取得します。

拡張(この記事では証明なし):d = gcd(a、b)とします。より一般的な方程式a * x + b * y = cの場合、d | cの場合にのみ解があります。a * x + b * y = dから得られた特別な解のセットがx0、y0であるとすると、方程式の両辺を乗算し(c / d)、次に元の方程式の特別な解のセット(c / d)x0を乗算します。 、(c / d)y0、元の方程式の一般的な解は次のとおりです。

この質問の解決策:質問で与えられた合同式はa * x + b * y = 1(yは整数)と同等であり、この質問は必ず解決策があるため、gcd(a、b)| 1、つまりgcd(a、 b)= 1。拡張ユークリッドアルゴリズムを使用して、特別な解x0、y0を見つけます。xの一般的な解はx = x0 + k * b(kは整数です)です。質問では最小の正の整数解が必要であることに注意してください。

コード

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll a,b,x,y;
void exgcd(ll a,ll b,ll &x,ll &y)
{
	if(!b) {x=1,y=0; return;}
	exgcd(b,a%b,x,y);
	ll z=x; x=y; y=z-(a/b)*y;
}

int main()
{
	scanf("%lld%lld",&a,&b);
	exgcd(a,b,x,y); //求出特解 
	x=(x%b+b)%b; //求出最小正整数解 
	printf("%lld\n",x); 
	
	return 0;
}

おすすめ

転載: blog.csdn.net/zjgmartin/article/details/108415336