[HEOI2016 / TJOI2016] + NTTスターリング数を合計します

説明

バリュー計算機能

\ [F(N)= \和\ limits_ {I = 0} ^ {N} \和\ limits_ {J = 0} ^ {I} 2 ^ J \回J!\回S(i、j)は\]

解決

みなさん、こんにちは、私は練習をプッシュしています半日は個人的な生活を実践するために(newbielyx \)\

\ [F(N)= \和\ limits_ {I = 0} ^ {N} \和\ limits_ {J = 0} ^ {I} 2 ^ J \回J!\回S(i、j)は\]

\ [= \和\ limits_ ^ {n}は{I 0 =} \和\ limits_ {J = 0} ^ {I} 2 ^ J \回J!\回\ FRAC {1} {J!} \回\左(\和\ limits_ {K = 0} ^ {J}(-1)^ K C(J、K)(JK)^ I \右)\ ]

\ [= \和\ limits_ {I = 0} ^ {N} \和\ limits_ {J = 0} ^ {I} 2 ^ J \和\ limits_ {K = 0} ^ {J}(-1)^ K C(j、k)は(JK)^ I \]

\ [= \和\ limits_ {J = 0} ^ {n}は2 ^ J \和\ limits_ {I = J} ^ {N} \和\ limits_ {K = 0} ^ {J}(-1)^ K C(j、k)は(JK)^ I \]

\ [= \和\ limits_ {J = 0} ^ {n}は2 ^ J \和\ limits_ {K = 0} ^ {J}(-1)^ k個のC(J、K)\和\ limits_ {I = 0} ^ {N}(JK)^ I \]

\ [= \和\ limits_ {J = 0} ^ {n}は2 ^ J \和\ limits_ {K = 0} ^ {J}(-1)^ K \ FRAC {J!} {K!(JK) !} \和\ limits_ {I = 0} ^ {N}(JK)^ I \]

\ [= \和\ limits_ {J = 0} ^ {n}は2 ^ J \ CDOT J!\和\ limits_ {K = 0} ^ {J} \ FRAC {( - 1)^ K} {!K} \ FRAC {\和\ limits_ {I = 0} ^ {N}(JK)^ I} { (JK)!} \]

上記の幾何学的なシーケンスは、続けていることを確認することは容易ですダウン

\ [F(N)= \和\ limits_ {J = 0} ^ {n}は2 ^ J \ CDOT J!\和\ limits_ {K = 0} ^ {J} \ FRAC {( - 1)^ K}、{K!} \ FRAC {(JK)^ {N + 1} -1} {(JK-1)(JK )!} \]

\ [= \和\ limits_ {J = 0} ^ {n}は2 ^ J \ CDOT J!\和\ limits_ {K = 0} ^ {J} \ FRAC {( - 1)^ K} {!K} \ FRAC {(JK)^ {N + 1} -1} {(JK)(jk-! 1)} \]

その後、ボリュームを上げ見つけることができます!

コード

#include <bits/stdc++.h>
using namespace std;

inline int ty() {
    char ch = getchar(); int x = 0, f = 1;
    while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); }
    while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
    return x * f;
}

typedef long long ll;
const ll P = 998244353, G = 3, Gx = 332748118;
const int _ = 4e5 + 10;
int N, r[_];
ll fac[_], facinv[_], A[_], B[_];

ll fpow(ll a, ll b) {
    ll ret = 1;
    for ( ; b; b >>= 1) {
        if (b & 1) ret = ret * a % P;
        a = a * a % P;
    }
    return ret;
}

inline void pre() {
    fac[0] = fac[1] = 1;
    for (int i = 2; i <= N; ++i) fac[i] = fac[i - 1] * i % P;
    facinv[0] = 1, facinv[N] = fpow(fac[N], P - 2);
    for (int i = N - 1; i >= 1; --i) facinv[i] = facinv[i + 1] * (i + 1) % P;
    for (int i = 0; i <= N; ++i) {
        A[i] = (i & 1) ? -1 : 1;
        A[i] = (A[i] * facinv[i] + P) % P;
    }
    for (int i = 2; i <= N; ++i) {
        B[i] = (fpow(i, N + 1) - 1 + P) % P;
        B[i] = B[i] * facinv[i] % P;
        B[i] = B[i] * fpow(i - 1, P - 2) % P;
    }
    B[0] = 1, B[1] = N + 1;
}

void NTT(int lim, ll *a, int op) {
    for (int i = 0; i < lim; ++i)
        if (i < r[i]) swap(a[i], a[r[i]]);
    for (int len = 2; len <= lim; len <<= 1) {
        int mid = len >> 1;
        ll Wn = fpow(op == 1 ? G : Gx, (P - 1) / len);
        for (int i = 0; i < lim; i += len) {
            ll w = 1;
            for (int j = 0; j < mid; ++j, w = w * Wn % P) {
                ll x = a[i + j], y = w * a[i + j + mid] % P;
                a[i + j] = (x + y) % P;
                a[i + j + mid] = (x - y + P) % P;
            }
        }
    }
}

inline void solve() {
    int lim = 1, k = 0;
    while (lim <= N + N) lim <<= 1, ++k;
    for (int i = 0; i < lim; ++i) r[i] = (r[i >> 1] >> 1) | ((i & 1) << (k - 1));
    NTT(lim, A, 1);
    NTT(lim, B, 1);
    for (int i = 0; i < lim; ++i) A[i] = (A[i] * B[i]) % P;
    NTT(lim, A, -1);
    ll inv = fpow(lim, P - 2);
    for (int i = 0; i <= N + N; ++i) A[i] = A[i] * inv % P;
}

int main() {
#ifndef ONLINE_JUDGE
    freopen("sum.in", "r", stdin);
    freopen("sum.out", "w", stdout);
#endif
    N = ty();
    pre();
    solve();
    ll ans = 0, t = 1;
    for (int i = 0; i <= N; ++i, t = t * 2 % P) ans = (ans + t * fac[i] % P * A[i] % P) % P;
    printf("%lld\n", ans);
    return 0;
}

おすすめ

転載: www.cnblogs.com/newbielyx/p/12110691.html