逆元与逆元存在的条件
设 inv[b] 是 b 的逆元, 那么 (a/b) %p = (a*inv[b]) %p
一个数 x 在模 p 的条件下不一定有逆元, x 关于 p 的逆元存在 当且仅当 x 和 p 互质
这里有一个推导: (设 a 为 x 的逆元, b为任意整数)
求法一:基于费马小定理的快速幂
只有在 p 是质数的情况下才可以使用
首先我们设 inv(a) 是 a 的逆元 那么根据定义, inv(a)∗a≡1(mod p)
再根据 费马小定理 ap−1≡1 , 易得 inv(a)∗a≡ap−1(mod p)
移项,得: inv(a)≡ap−2
于是我们得到了快速幂模算法的一个前提条件: inv(a)≡ap−2(mod p)
int n,p;
int ksm(int x,int y)
{
int ret=1;
while(y)
{
if(y&1) ret=ret*x%p;
x=x*x%p;
y=y>>1;
}
return ret;
}
int main()
{
n=read();p=read();
for(int i=1;i<=n;i++)
{
printf("%d",ksm(i,p-2));
}
return 0;
}
求法二:扩欧
a和b互质,条件更宽松
不加证明的给出代码
void exgcd(ll a,ll b,ll &x,ll &y)
{
if(b==0)
{
x=1;y=0;return ;
}
exgcd(b,a%b,x,y);
ll t=x;x=y;y=t-(a/b)*y;
}
int main()
{
n=read();p=read();
for(ll i=1;i<=n;i++)
{
ll inv,y;
exgcd(i,p,inv,y);
inv=(inv+p)%p;
cout<<inv<<endl;
}
return 0;
}
inv[1]=1;
cout<<1<<endl;
for(i=2;i<=n;i++)
{
inv[i]=(p-(p/i))*inv[p%i]%p;
printf("%d\n",inv[i]);
}