关于逆元&&lucas定理
lucas是求组合数C(m,n)%p,有一个公式:C(m,n) = C(m/p,n/p)*C(m%p,n%p)。
(a*b)%c==a%c*b%c,但是(a/b)%c!=a%c/b%c,所以我们要算b在c意义下的乘法逆元。
一个线性求乘法逆元。a[i] = (p - p / i) * a[p % i] % p;或者是费马小定理,i在p下的逆元就是i^(p - 2)。然后从后往前推。
两种代码:
第一种:
for(int i=2;i<=n+m;i++)
a[i]=(p-p/i)*a[p%i]%p;
for(int i=2;i<=n+m;i++)
a[i]=a[i-1]*a[i]%p;
第二种:
for(int i = 1;i <= n;i++) sum[i] = sum[i - 1] * i % p;//阶乘 inv[k] = pow(sum[k],p - 2); for(int i = k - 1;i >= 0;i--) { inv[i] = inv[i + 1] * (i + 1) % p;//阶乘逆元 }
然后是lucas:
int lucas(int x,int y) { if(x < y) return 0; else if(x < p) return sum[x] * inv[y] * inv[x-y] % p; else return lucas(x/p,y/p) * lucas(x%p,y%p) % p; }
只想找一个不会伤害我的人