QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#51106#1285. Stirling Numberckiseki#AC ✓8326ms68284kbC++5.1kb2022-09-30 20:25:482022-09-30 20:25:48

Judging History

你现在查看的是最新测评结果

  • [2023-08-10 23:21:45]
  • System Update: QOJ starts to keep a history of the judgings of all the submissions.
  • [2022-09-30 20:25:48]
  • 评测
  • 测评结果:AC
  • 用时:8326ms
  • 内存:68284kb
  • [2022-09-30 20:25:48]
  • 提交

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"