阶乘
\(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;
}
|