线性求逆元
求逆元可以用费马小定理或者扩展欧几里得,也可以用如下的O(n)算法:(背下来)
这个对p是有要求的,p(也就是模数)必须是质数
p不是质数的话,就用扩展欧几里得比较方便了(两个数有逆元当且仅当互质!)
inv[1]=1;
for(i=2;i<=p;i++)
inv[i]=(p-p/i)*inv[p%i]%p
也可以用另一个O(n)的方法
经过一堆证明:
先用快速幂费马小定理求出B[n](B[n]=inv[n!],而n!可以用线性来做。注意模p哦。复杂度是O(log(n)),与后来的O(n)一加就可以删去前者了!)
因为inv[n]*B[n-1]=B[n]
又因为B[n-1]*(n-1)!=1
所以方程左右两边同时乘以(n-1)!,得
inv[n]=B[n]*A[n-1]*************(A[n]=n!,O(n)可得该数组)
完美。0w0。
我也不知道这样可以干嘛,我想想。。。我大概听了一节假的数论。
补充一下怎么利用B[n]把B数组也给求出来吧~
B[n-1]*inv[n]=B[n]
同理,我们在方程的左右两边同时乘以n,得:
B[n-1]=B[n]*n
qwq再来一次O[n],真完美呀真完美,B[ ]数组也求出来了。
人类的本质就是复读机。
——rxz
那么知道这些(A[ ],B[ ],inv[ ],当然是在模p意义下),至少可以拎过来求组合数:
C(n,m)=A[n]%p*B[m]%p*B[n-m]%p。
这样就可以O(2*n+log(n))预处理,O(1)输出。
快到飞起!麻麻再也不用担心我超时啦!