主要绕过费马小定理来证明lucas定理,挺有意思..此外设置多进制计算机可以通过移位运算直接加快多进制运算的速度。
1.Lucas定理
Lucas定理详解
。
这里n,m
可能很大,比如达到 1015 ,而 p 在 109以内。显然运用常规的阶乘方法无法直接求解,所以引入Lucas定理。
Lucas定理
把n
和 m 写成 p 进制数的样子(如果长度不一样把短的补成长的那个的长度):n=(a0a1…ak)p
m=(b0b1…bk)p
那么:
(nm)≡∏ki=0(aibi)modp
证明
如果把Lucas定理从递归的角度理解,它其实是这样的:
设n=ap+b,m=cp+d,(b,d<p,a=⌊np⌋,c=⌊mp⌋)(nm)≡(ac)∗(bd)
这个定理的一个很巧妙的证法是通过二项式定理来说明上面的式子是成立的。
首先,对于任意质数pp,有:
(1+x)p≡1+xpmodp
其证明可以由费马小定理(xp≡xmodp) |p为素数)
直接得出:(1+x)p≡1+x
xp≡x
所以 (1+x)p≡1+x≡1+xp
(当然同样也有(a+b)p≡ap+bpmodp
,具体为什么你可以拆开前面的式子,将其除 ap 和 bp 项外的所有项的系数好好研究一下(其实就是杨辉三角的第p层),可以发现把对称项系数分别合并后都能整除 p)
利用这个性质,我们证明Lucas定理:
(1+x)n=(1+x)⌊np⌋∗p(1+x)b=(1+xp)⌊np⌋(1+x)b=∑i=0k(⌊np⌋i)xpi∑j=0k(bj)xj
考察等式左右两边xmxm的系数,可以发现:
左边右边=(nm)=(⌊np⌋i)(bj),(pi+j=m,j<p)=(⌊np⌋⌊mp⌋)(bd)
所以上面的式子成立,证明完毕。
如果不算预处理什么的,算法时间复杂度为O(logpn)
。如果能够支持预处理,那么就加一个 O(p) ,要不就用快速幂,乘上 O(logp) 。2. 线性求所有逆元的方法
的做法发现太神了,虽然想起来是挺简单的
这个做法实际上是这样的,首先 1−1≡1(modp)
然后我们设 p=k⋅i+r, r<i, 1<i<p
再将这个式子放到modp
意义下就会得到
k⋅i+r≡0(modp)
两边同时乘上 i−1⋅r−1
就会得到
k⋅r−1+i−1i−1i−1≡≡≡0−k⋅r−1−⌊pi⌋⋅(pmodi)−1(modp)(modp)(modp)
于是就可以从前面推出当前的逆元了,代码也就一行
A[i] = -(p / i) * A[p % i];
Related posts: