移動:自分のブログ
トピック
回答
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;
}