lucas定理 模板
lucas定理
先预先求出.
并利用费马小定理和快速幂乘求出每一个的逆元。求,当直接就是.若都在范围内,则直接转化为.否则就是lucas定理缩小规模。
[对一个固定的p,预处理求阶乘及快速模幂求其逆元,时间复杂度。空间复杂度。预处理之后,单次求复杂度]{}
洛谷P3807模板题
void prepare(ll p, vector<ll>&fac, vector<ll>&inv_fac) {
fac.resize(p); inv_fac.resize(p);
mod_sys mod;
mod.set_mod(p);
fac[0] = 1;
inv_fac[0] = 1;
for (int i = 1; i < p; ++i) {
fac[i] = (fac[i-1]*i)%p;
inv_fac[i] = mod.pow(fac[i], p-2); // 既然能枚举一遍,p*p不应该爆ll
}
}
// 输入预设0=<n,m<p
inline ll combination(ll n, ll m, ll p, vector<ll>&fac, vector<ll>&inv_fac) {
if (n < m) return 0;
return fac[n]*inv_fac[m]%p*inv_fac[n-m]%p;
}
ll lucas(ll n, ll m, ll p, vector<ll>&fac, vector<ll>&inv_fac) {
if (n < m) return 0;
ll ans = 1;
while(true) {
if (m == 0) return ans;
if (n < p && m < p) return ans*combination(n,m,p,fac,inv_fac)%p;
ans = ans * combination(n%p,m%p,p,fac,inv_fac)%p;
n/=p; m/=p;
}
}

浙公网安备 33010602011771号