目录
题目描述
求关于xx的同余方程 a x \equiv 1 \pmod {b}ax≡1(modb) 的最小正整数解。
输入格式
一行,包含两个正整数 a,ba,b,用一个空格隔开。
输出格式
一个正整数 x_0x0,即最小正整数解。输入数据保证一定有解。
样例输入
3 10
样例输出
7
问题提示
【数据范围】
对于 40%的数据,2 ≤b≤ 1,0002≤b≤1,000;
对于 60%的数据,2 ≤b≤ 50,000,0002≤b≤50,000,000;
对于 100%的数据,2 ≤a, b≤ 2,000,000,0002≤a,b≤2,000,000,000。
扩展欧几里得
先来说一下扩展欧几里得求解的解
Ax + By = C = gcd(A, B)
∵ gcd(A, B) = gcd(B, A mod B)
∵ Bx’ + (A mod B)y’ = gcd(B, A mod B)
∴ Bx’ + (A mod B)y’ = gcd(A, B)
∴ Bx’ + (A - A/B * B)y’ = gcd(A, B)
→ Bx’ + Ay’ - B*(A/B)y’ = gcd(A, B)
→ Ay’ + B(x’ - (A/B)*y’) = gcd(A, B)
∴ x = y’, y = x’ -(A/B)*y’
所以我们可以得到代码
int exgcd(int a,int b,int &x,int &y)
{
if(b==0)
{
x=1;
y=0;
return a;
}
int g=exgcd(b,a%b,x,y);
int z=x;
x=y;
y=z-(a/b)*y;
return g;
}
求解逆元
,x就是a在%p下的逆元
根据裴蜀定理对于gcd(a,b)=1
ax+by=1
求解逆元的方式
1.扩展欧几里得
2.费马小定理
3.线性求逆元
现在先来说一下扩展欧几里得求逆元的方式
signed main()
{
cin>>a>>b;
exgcd(a,b,x,y);
cout<<(x%b+b)%b;
/*
ax+by
求出的x是线性方程的一组特解
a(x+db)+b(y-da)=ax+adb+by-adb=1
整数 x
负数 (x%b+b)%b
*/
return 0;
}
Code
#include <iostream>
using namespace std;
#define int long long
#define F(i,a,b) for(int i=(a);i<=(b);i++)
#define f(i,a,b) for(int i=(a);i>=(b);i--)
int x,y,a,b;
int exgcd(int a,int b,int &x,int &y)
{
if(b==0)
{
x=1;
y=0;
return a;
}
int g=exgcd(b,a%b,x,y);
int z=x;
x=y;
y=z-(a/b)*y;
return g;
}
signed main()
{
cin>>a>>b;
exgcd(a,b,x,y);
cout<<(x%b+b)%b;
/*
ax+by
求出的x是线性方程的一组特解
a(x+db)+b(y-da)=ax+adb+by-adb=1
整数 x
负数 (x%b+b)%b
*/
return 0;
}