【NOIP2012D2T1】同余方程

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。

分析

已知 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;
}

猜你喜欢

转载自blog.csdn.net/disangan233/article/details/80981762
今日推荐