QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#51106 | #1285. Stirling Number | ckiseki# | AC ✓ | 8326ms | 68284kb | C++ | 5.1kb | 2022-09-30 20:25:48 | 2022-09-30 20:25:48 |
Judging History
answer
#include <bits/stdc++.h>
using namespace std;
template <int mod, int G, int maxn>
class NTT {
private:
static_assert(maxn == (maxn & (-maxn)));
static_assert((mod - 1) % maxn == 0);
int roots[maxn];
public:
constexpr static int add(int a, int b) { return a + b >= mod ? a + b - mod : a + b; }
constexpr static int sub(int a, int b) { return a - b < 0 ? a - b + mod : a - b; }
constexpr static int mul(int64_t a, int64_t b) { return static_cast<int>(a * b % mod); }
constexpr static int qpow(int a, int64_t k) {
int r = 1 % mod;
while (k) {
if (k & 1) r = mul(r, a);
k >>= 1; a = mul(a, a);
}
return r;
}
constexpr static int minv(int a) { return qpow(a, mod - 2); }
NTT() : roots{} {
int r = qpow(G, (mod - 1) / maxn);
for (int i = maxn / 2; i; i /= 2) {
roots[i] = 1 % mod;
for (int j = 1; j < i; ++j)
roots[i + j] = mul(roots[i + j - 1], r);
r = mul(r, r);
}
}
void operator()(int F[], int n, bool inv = false) {
for (int i = 0, j = 0; i < n; ++i) {
if (i < j) swap(F[i], F[j]);
for (int k = n / 2; (j ^= k) < k; k /= 2);
}
for (int s = 1; s < n; s *= 2) {
for (int i = 0; i < n; i += s * 2) {
for (int j = 0; j < s; ++j) {
int a = F[i + j];
int b = mul(F[i + j + s], roots[s + j]);
F[i + j] = add(a, b);
F[i + j + s] = sub(a, b);
}
}
}
if (inv) {
int invn = minv(n);
for (int i = 0; i < n; ++i)
F[i] = mul(F[i], invn);
reverse(F + 1, F + n);
}
}
};
static constexpr int maxn = 1 << 21;
static constexpr int M1 = 985661441;
static constexpr int M2 = 998244353;
static constexpr int M3 = 1004535809;
using NTT1 = NTT<M1, 3, maxn>;
using NTT2 = NTT<M2, 3, maxn>;
using NTT3 = NTT<M3, 3, maxn>;
NTT1 ntt1;
NTT2 ntt2;
NTT3 ntt3;
int superBigCRT(int64_t A, int64_t B, int64_t C, int mod) {
static constexpr int64_t r12 = NTT2::qpow(M1, M2 - 2);
static constexpr int64_t r13 = NTT3::qpow(M1, M3 - 2);
static constexpr int64_t r23 = NTT3::qpow(M2, M3 - 2);
const int64_t M1M2 = int64_t(M1) * M2 % mod;
B = (B - A + M2) * r12 % M2;
C = (C - A + M3) * r13 % M3;
C = (C - B + M3) * r23 % M3;
return (A + B * M1 + C * M1M2) % mod;
}
void conv(vector<int> &a, vector<int> &b, int mod) {
const size_t sa = a.size(), sb = b.size();
int sz = 1;
while (sz < a.size() + b.size()) sz *= 2;
a.resize(sz);
b.resize(sz);
auto a1 = a, a2 = a;
auto b1 = b, b2 = b;
ntt1(a1.data(), sz);
ntt1(b1.data(), sz);
for (int i = 0; i < sz; ++i) a1[i] = NTT1::mul(a1[i], b1[i]);
ntt1(a1.data(), sz, true);
ntt2(a2.data(), sz);
ntt2(b2.data(), sz);
for (int i = 0; i < sz; ++i) a2[i] = NTT2::mul(a2[i], b2[i]);
ntt2(a2.data(), sz, true);
ntt3(a.data(), sz);
ntt3(b.data(), sz);
for (int i = 0; i < sz; ++i) a[i] = NTT3::mul(a[i], b[i]);
ntt3(a.data(), sz, true);
a.resize(sa + sb - 1);
for (size_t i = 0; i < a.size(); ++i)
a[i] = superBigCRT(a1[i], a2[i], a[i], mod);
}
// \Pi_{l <= i < r} (x + a[i])
vector<int> getPoly(int l, int r, int mod) {
assert (l <= r);
if (l == r) {
return {1};
}
if (r - l == 1) {
return {l, 1};
}
int m = (l + r) >> 1;
auto lhs = getPoly(l, m, mod);
auto rhs = getPoly(m, r, mod);
conv(lhs, rhs, mod);
return lhs;
}
using ll = int64_t;
int fac[maxn], ifac[maxn], inv[maxn];
int C(int64_t n, int64_t k, int p) {
if (k < 0 || n < k)
return 0;
if (n < p && k < p) {
return 1LL * fac[n] * ifac[k] * ifac[n-k] % p;
}
return 1LL * C(n % p, k % p, p) * C(n / p, k / p, p) % p;
}
map<tuple<int64_t,int64_t>, int> mp;
int f(int64_t n, int64_t k, int p) {
if (k > n) return 0;
if (mp.count({ n, k })) {
return mp[{n,k}];
}
int64_t res = 0;
for (int64_t i = p*(k/p); i <= k; i++) {
if ((n - i) % 2 == 0)
res += C(n, i, p);
else
res -= C(n, i, p);
if (res >= p) res -= p;
if (res < 0) res += p;
}
mp[{n,k}] = res;
assert(mp.size() <= 100);
return res;
}
int solve(ll n, ll pre, int p) {
pre -= n / p;
if (pre < 0)
return 0;
int r = n % p;
int64_t ans = 0;
auto coef = getPoly(0, r, p);
for (int k = 0; k <= r; k++) {
if (pre - k < 0) continue;
ans += 1LL * coef[k] * f(n / p, (pre - k) / (p - 1), p);
ans %= p;
}
return ans;
}
int main() {
cin.tie(nullptr)->sync_with_stdio(false);
ll n, l, r;
int p;
cin >> n >> l >> r >> p;
fac[0] = ifac[0] = 1; inv[1] = 1;
for (int i = 2; i < p; i++)
inv[i] = 1LL * inv[p % i] * (p - p / i) % p;
for (int i = 1; i < p; i++) {
fac[i] = 1LL * fac[i-1] * i % p;
ifac[i] = 1LL * ifac[i-1] * inv[i] % p;
}
cout << (solve(n, r, p) - solve(n, l - 1, p) + p) % p << '\n';
// int x; cin >> x;
return 0;
}
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 100
Accepted
time: 30ms
memory: 28236kb
input:
4 1 4 5
output:
4
result:
ok "4"
Test #2:
score: 0
Accepted
time: 32ms
memory: 28148kb
input:
6 5 5 29
output:
15
result:
ok "15"
Test #3:
score: 0
Accepted
time: 62ms
memory: 39988kb
input:
1000 685 975 999983
output:
482808
result:
ok "482808"
Test #4:
score: 0
Accepted
time: 35ms
memory: 28140kb
input:
8 7 8 7
output:
1
result:
ok "1"
Test #5:
score: 0
Accepted
time: 34ms
memory: 28112kb
input:
6 4 6 3
output:
2
result:
ok "2"
Test #6:
score: 0
Accepted
time: 27ms
memory: 28284kb
input:
31494923 16387579 27674098 2
output:
0
result:
ok "0"
Test #7:
score: 0
Accepted
time: 945ms
memory: 35744kb
input:
1000000000 179971578 813833436 383101
output:
53093
result:
ok "53093"
Test #8:
score: 0
Accepted
time: 838ms
memory: 35340kb
input:
1000000000 243662537 919841454 336437
output:
75332
result:
ok "75332"
Test #9:
score: 0
Accepted
time: 207ms
memory: 40532kb
input:
1000000000 802415407 880806868 999983
output:
960771
result:
ok "960771"
Test #10:
score: 0
Accepted
time: 193ms
memory: 40432kb
input:
1000000000 644768002 859679621 999983
output:
805072
result:
ok "805072"
Test #11:
score: 0
Accepted
time: 209ms
memory: 40488kb
input:
1000000000 413491669 805704689 999983
output:
138470
result:
ok "138470"
Test #12:
score: 0
Accepted
time: 8326ms
memory: 68284kb
input:
48537068788 22847195743 28163317559 999983
output:
529264
result:
ok "529264"
Test #13:
score: 0
Accepted
time: 3780ms
memory: 53720kb
input:
828536325370 779765412000 782633091631 999983
output:
836701
result:
ok "836701"
Test #14:
score: 0
Accepted
time: 3465ms
memory: 53716kb
input:
258077969836231211 200983000620029238 226661348290193221 999983
output:
104488
result:
ok "104488"
Test #15:
score: 0
Accepted
time: 7561ms
memory: 68260kb
input:
258904208719347339 185679775210965354 223112834501603079 999983
output:
0
result:
ok "0"
Test #16:
score: 0
Accepted
time: 1755ms
memory: 46536kb
input:
259730451897430763 53367210716367086 159749126385022258 999983
output:
0
result:
ok "0"
Test #17:
score: 0
Accepted
time: 7599ms
memory: 68176kb
input:
260556695075514187 28149045695465635 29562653808086859 999983
output:
669091
result:
ok "669091"
Test #18:
score: 0
Accepted
time: 861ms
memory: 42052kb
input:
1000000000000000000 199156813867768126 571262092911942493 919337
output:
732102
result:
ok "732102"
Test #19:
score: 0
Accepted
time: 7267ms
memory: 68252kb
input:
353534534534 1999983 2234324324 999983
output:
613376
result:
ok "613376"
Test #20:
score: 0
Accepted
time: 3624ms
memory: 64420kb
input:
353534534534 0 2234324324 999983
output:
520965
result:
ok "520965"
Test #21:
score: 0
Accepted
time: 7097ms
memory: 68180kb
input:
353534534534 22342343 353534534534 999983
output:
281927
result:
ok "281927"