线性求逆元

求逆元可以用费马小定理或者扩展欧几里得,也可以用如下的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)输出。

快到飞起!麻麻再也不用担心我超时啦!

原文地址:https://www.cnblogs.com/nishida-rin/p/12271127.html