逆元、exgcd以及威尔逊定理等等

written by oneman233
2019-08-24

逆元相关

取余有很多好性质:

(a+b)%c=(a%c+b%c)%c(ab)%c=(a%cb%c)%c

但是对于(a/b)%p,以上性质不能使用,只能用下面这条式子:

(a/b)%p=(ab1)%p

上式中b1称为bmod p意义下的逆元。

逆元有这样的性质:

bb11(mod p)

逆元的求解方法主要有三种:

费马小定理加快速幂

费马小定理:

如果p是一个质数,而整数a不是p的倍数,则有ap11(mod p)

注意只适用于p是质数且a不是p的倍数的情况:

b1(mod p)bp2(mod p)

exgcd

void exgcd(int a,int b,int &x,int &y) {
    if(!b) x=1,y=0;
    else exgcd(b,a%b,y,x),y-=a/b*x;
    int x,y;
    exgcd(a,p,x,y);
    x=(x%p+p)%p;
}

此时xa在模p意义下的逆元,要求ap互质,p可以不为质数。

为了证明上述过程的正确性,先介绍exgcd算法:

已知整数ab,扩展欧几里得算法可以在求得ab的最大公约数的同时,找到整数xy(其中一个很可能是负数),使它们满足贝祖等式:ax+by=gcd(a,b)

贝祖定理:

定理描述如下:

a,bZ+exist x,y, ax+by=cgcd(a,b)|c

实际上观察:

ax1(mod p)

可以化成:

axpy1(mod p)

不妨把上式中的减号改成加号,得到:

ax+py1(mod p)

由于ap互质,即gcd(a,b)=1,套用exgcd即可。

这里有两个有意思的结论:

  1. 如果xy互质,那么不可用$xa+ybx*y-x-yab$都为自然数。
  2. aixi 均为整数时, a1x1+a2x2++anxn的值一定为gcd(a1,a2,,an)的整数倍。

这道题中会用到。

线性递推

有时候可能需要预处理一大堆数据在模p意义下的逆元,这时候需要用到逆元的线性递推式。

inv[1]=1;
inv[i]=(p-p/i)*inv[p%i]%p;

简单证明如下:

首先:

111(mod p)

设:

p=ki+r

即:

k=p/i,r=p%i

则:

ki+r0(mod p)

上式两边同时乘以:

i1r1

得到:

kii1r1+ri1r10(mod p)

注意到:

ii11(mod p)rr11(mod p)

得到:

kr1+i10(mod p)

化简:

i1kr1(mod p)

即:

i1p/i(p%i)1(mod p)

为了防止负数取余,可以加上一个p

i1(pp/i)(p%i)1(mod p)

证毕。

关于阶乘的逆元

做卢卡斯定理的时候可能会搞出很大数字的阶乘逆元,费马小定理显得太慢,可以线性递推出所有阶乘的逆元:

fac[0]=fac[1]=1;
for(int i=2;i<=MAXN;i++)
    fac[i]=fac[i-1]*i%mod;
inv[MAXN]=qpow(fac[MAXN],mod-2);
for(int i=MAXN-1;i>=0;i--)
    inv[i]=inv[i+1]*(i+1)%mod;

这样考虑:

inv[i+1]1(i+1)!(mod p)

那么就有:

inv[i+1](i+1)1i!(mod p)=inv[i]

用费马小定理求出一个,其他的就可以用上式递推出来。

威尔逊定理

当且仅当p为素数时:

(p1)!1(mod p)

素数的一个牛逼充要条件,但是不甚实用,阶乘会爆炸增长。

0 条评论
未登录用户
支持 Markdown 语法

来做第一个留言的人吧!