乘法逆元通常说的是模意义下的乘法逆元,ax ≡ 1(mod b)则 x 称为 a mod b 的逆元
洛谷:https://www.luogu.com.cn/problem/P3811
我们首先考虑扩展欧几里得算法:
ax + by = gcd (a,b);
我们变换乘法逆元的公式:ax ≡ 1 (mod b)
(ax) % b = 1
ax - by = 1
这个形式看着是不是很熟悉
咱们再来回顾一下扩展欧几里得算法:
int exgcd(int a,int b,int &x,int &y)
{
if(!b)
{
x = 1,y=0;
return a;
}
else
{
int d = exgcd(b,a%b,y,x);
y -= a/b *x;
return d;
}
}
但是由于上面的题很坑,被卡常
所以我们一顿操作下来:
#include<bits/stdc++.h>
using namespace std;
//快读
template <typename L> inline void Read(L &x){
char c;
while((c=getchar())<'0'||c>'9');
x=c^48;
while((c=getchar())>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48);
}
//快写
template <typename L> void Write(L x){
if(x>9) Write(x/10);
putchar(x%10^48);
}
//扩欧
inline void exgcd(register int a,register int b,register int &x,register int &y){
if(!b){x=1;y=0;}
else{
exgcd(b,a%b,x,y);
register int k=x;
x=y;y=k-(a/b)*y;
}
}
int main(){
register int n,p,x,y;
Read(n);Read(p);
for(register int i=1;i<=n;++i){
exgcd(i,p,x,y);
Write(x<0?x+p:x);
putchar('\n');
}
return 0;
}
我们来看一个新的算法:
快速幂法:
当 p 为质数的时候,ax ≡ 1 (mod p)
根据费马小定理
上代码:
int qpow(int a,int b)
{
int res =1;
while(b)
{
if(b&1) res =(LL)res * a % p;
b>>=1;
a = a*a % p;
}
return res;
}
接下来,我们来看一下线性同余方程:
形如:ax ≡ c (mod b)
没错就是乘法逆元但是系数变成了整数
ax - by = c
而扩欧是可以求出一组 x,y 使得 ax + by = gcd(a,b)
因此,我们获得整数解的条件就是 gcd(a,b) | c;
我们在公式两边同时除以gcd(a,b) 乘 c
这样我们就可以获得一组解了
上代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
int exgcd(int a,int b,int &x,int &y)
{
if(!b)
{
x = 1,y=0;
return a;
}
else
{
int d = exgcd(b,a%b,y,x);
y -= a/b *x;
return d;
}
}
int n;
int main()
{
int a,b,c;
scanf("%d%d%d",&a,&c,&b);
int x,y;
int d = exgcd(a,b,x,y);//gcd(a,b)
if(c % d)puts("-1");
else printf("%d\n",(LL)x*(c/d)%b);
}