跳转至

阶乘

\(n!\)

P5282 【模板】快速阶乘算法 - 洛谷

\(n!\mod p\), 保证 \(p\) 为质数, \(n,p\leq2^{31}-1\)

多项式任意模数乘法+多项式连续点值平移

代码
C++
{ 多项式基础模版 }
int st[64], tot;
i64 getFact(int n, int p) {
    int s = sqrt(n);
    int invs = qpow(s, p - 2, p);
    tot = 0;
    for (int i = s ; i > 1 ; i >>= 1) {
        st[tot++] = i;
    }
    Poly c = {1, (s + 1) % p};
    for (int j = tot - 1 ; j >= 0 ; j--) {
        int L = st[j];
        auto d = ValueTrans(c, L >> 1, (L >> 1) + 1, p);
        c.resize(2 * (int) c.size());
        for (int i = 0 ; i < (int) d.size() ; i++) {
            c[d.size() + i] = d[i];
        }
        d = ValueTrans(c, (int) c.size() - 1, 1LL * invs * (L >> 1) % p, p);
        for (int i = 0 ; i < (int) c.size() ; i++) {
            c[i] = 1LL * c[i] * d[i] % p;
        }
        if (L & 1) {
            for (int i = 0 ; i <= L ; i++) {
                c[i] = (1LL * i * s % p + L) % p * c[i] % p;
            }
        } else {
            c.resize(L + 1);
        }
    }
    i64 ans = 1;
    for (int i = 0 ; i < s ; i++) {
        ans = ans * c[i] % p;
    }
    for (int i = s * s + 1 ; i <= n ; i++) {
        ans = ans * i % p;
    }
    return ans;
}
\(\sum_{i=1}^ni!\)

\(\sum_{i=1}^n{i!}\mod p\), 保证 \(p\) 为质数, \(n,p\leq2^{31}-1\)

多项式任意模数乘法+多项式连续点值平移

代码
C++
{ 多项式基础模版 }
using namespace Polynomial;
int st[64], tot;
i64 getFactSum(int n, int p) {
    int s = sqrt(n);
    int invs = qpow(s, p - 2, p);
    tot = 0;
    for (int i = s ; i > 1 ; i >>= 1) {
        st[tot++] = i;
    }
    Poly tc[2], td[2];
    tc[0] = {2 % p, (s + 2) % p};
    tc[1] = {1, 1};
    for (int j = tot - 1 ; j >= 0 ; j--) {
        int L = st[j];
        for (int t = 0 ; t < 2 ; t++) {
            Poly &c = tc[t], &d = td[t];
            d = ValueTrans(c, L >> 1, (L >> 1) + 1, p);
            c.resize(2 * (int) c.size());
            for (int i = 0 ; i < (int) d.size() ; i++) {
                c[d.size() + i] = d[i];
            }
            d = ValueTrans(c, (int) c.size() - 1, 1LL * invs * (L >> 1) % p, p);
        }
        for (int i = 0 ; i < (int) tc[0].size() ; i++) {
            tc[1][i] = (1LL * tc[0][i] * td[1][i] + tc[1][i]) % p;
            tc[0][i] = 1LL * tc[0][i] * td[0][i] % p;
        }
        if (L & 1) {
            for (int i = 0 ; i <= L ; i++) {
                tc[1][i] = (tc[0][i] + tc[1][i]) % p;
                tc[0][i] = (1LL * i * s + L + 1) % p * tc[0][i] % p;
            }
        } else {
            tc[0].resize(L + 1);
            tc[1].resize(L + 1);
        }
    }
    i64 ans0 = 1, ans1 = 0;
    for (int i = 0 ; i < s ; i++) {
        ans1 = (ans0 * tc[1][i] + ans1) % p;
        ans0 = ans0 * tc[0][i] % p;
    }
    for (int i = s * s + 1 ; i <= n ; i++) {
        ans1 = (ans1 + ans0) % p;
        ans0 = ans0 * (i + 1) % p;
    }
    return ans1;
}