Description
求关于 x 的同余方程 ax ≡ 1 (mod b)的最小正整数解。
Input
输入只有一行,包含两个正整数 a, b,用一个空格隔开。
Output
输出只有一行,包含一个正整数 x0,即最小正整数解。输入数据保证一定有解。
Sample Input
3 10
Sample Output
7
Hint
【数据范围】
对于 40%的数据,2 ≤b≤ 1,000;
对于 60%的数据,2 ≤b≤ 50,000,000;
对于 100%的数据,2 ≤a, b≤ 2,000,000,000。
对于 40%的数据,2 ≤b≤ 1,000;
对于 60%的数据,2 ≤b≤ 50,000,000;
对于 100%的数据,2 ≤a, b≤ 2,000,000,000。
分析
已知 ax ≡ 1 (mod b),根据 同余定理 可以将其转换为 ax%b=1,设ax=by+1,所以ax-by=1,即ax+b(-y)=1。 根据 扩展欧几里德算法(扩欧) , 对于不完全为 0 的非负整数 a,b,gcd(a,b)表示 a,b 的最大公约数,必然 存在整数对 x,y ,使得 gcd(a,b)=ax+by。并且有个东西叫裴蜀定理:a,b互质的条件是ax+by=1,因为本题一定有解,所以gcd(a,b)=1,所以ax+b(-y)=gcd(a,b),此题结束。
关于扩展欧几里德算法的证明请看百度百科。
PS:由于扩欧的结果只满足|x|+|y|最小,由题目的要求x为正整数应该输出(x%b+b)%b(由于x+b可能还是小于0)。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register long long
ll a,b,x,y;
inline ll read()
{
re luoyang=0;
char did=getchar();
while(did<'0'||did>'9') did=getchar();
while(did>='0'&&did<='9')
luoyang=luoyang*10+did-'0',did=getchar();
return luoyang;
}
inline ll exgcd(ll a,ll b,ll &x,ll &y)
{
if(b==0)
{
x=1;y=0;
return a;
}
ll r=exgcd(b,a%b,x,y);
ll t=x;x=y;y=t-a/b*y;
return r;
}
int main()
{
a=read();b=read();
re gcd=exgcd(a,b,x,y);
x=(x%b+b)%b;
cout<<x;
return 0;
}