[NOIP2012 提高组] 同余方程(扩展欧几里得算法)
题目描述
求关于 $ x$ 的同余方程 a x ≡ 1 ( m o d b ) a x \equiv 1 \pmod {b} ax≡1(modb) 的最小正整数解。
输入格式
一行,包含两个整数 a , b a,b a,b,用一个空格隔开。
输出格式
一个整数 x 0 x_0 x0,即最小正整数解。输入数据保证一定有解。
样例 #1
样例输入 #1
3 10
样例输出 #1
7
提示说明
数据规模与约定
- 对于 40 % 40\% 40% 的数据, 2 ≤ b ≤ 1 , 000 2 ≤b≤ 1,000 2≤b≤1,000;
- 对于 60 % 60\% 60% 的数据, 2 ≤ b ≤ 50 , 000 , 000 2 ≤b≤ 50,000,000 2≤b≤50,000,000;
- 对于 100 % 100\% 100% 的数据, 2 ≤ a , b ≤ 2 , 000 , 000 , 000 2 ≤a, b≤ 2,000,000,000 2≤a,b≤2,000,000,000。
代码内容
// #include <iostream>
// #include <algorithm>
// #include <cstring>
// #include <stack>//栈
// #include <deque>//队列
// #include <queue>//堆/优先队列
// #include <map>//映射
// #include <unordered_map>//哈希表
// #include <vector>//容器,存数组的数,表数组的长度
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
//扩展欧几里得算法(裴蜀定理)
//根据费马定理,任意正整数a, b都存在整数x, y
//使得ax + by = gcd(a, b)
ll exgcd(ll a,ll b,ll &x,ll &y)
{
if(!b)
{
x=1,y=0;
return a;
}
ll d=exgcd(b,a%b,y,x);
y-=a/b*x;
return d;
}
int main()
{
ll a,b;
cin>>a>>b;
ll x,y;
//扩展欧几里得算法
//ax+by=gcd(a,b)=d
/*(1/d)*(a*x+b*y)=d*(1/d)*/
//a*x≡1(mod b)
//a*x=b*y+1
/*a*x+b*y=1*/
ll d=exgcd(a,b,x,y);
cout<<((x*(1/d))%(b/d)+(b/d))%(b/d)<<endl;
return 0;
}