CF1528F AmShZ Farm 題解

JiaY19發表於2024-05-24

思路

首先,原題意要你求:

\[\sum_{i=0}^n \binom{n}{i}i^kn^{n-i} \]

其實比較板子吧。

\[\sum_{i=0}^n \binom{n}{i}i^kn^{n-i} \]

\[\begin{aligned} &=\sum_{i=0}^{n}\binom{n}{i}\sum_{j=1}^k {k\brace j}\binom{i}{j}j! n^{n-i}&(\text{普通冪拆開})\\ &=\sum_{j=1}^k{k\brace j}j!\sum_{i=0}^n\binom{n}{i}\binom{i}{j}n^{n-i}\\ &=\sum_{j=1}^k{k\brace j}j!\sum_{i=0}^n\frac{n!i!}{i!(n-i)!j!(i-j)!}n^{n-i}\\ &=\sum_{j=1}^k{k\brace j}n!\sum_{i=0}^n\frac{n^{n-i}}{(n-i)!(i-j)!}\\ &=\sum_{j=1}^k{k\brace j}\frac{n!}{(n-j)!}\sum_{i=0}^n\binom{n-j}{n-i}n^{n-i}\\ &=\sum_{j=1}^k{k\brace j}\frac{n!}{(n-j)!}(1+n)^{n-j}&(\text{二項式定理})\\ &=\sum_{j=1}^k\frac{1}{j!}\sum_{i=0}^j\binom{j}{i}(-1)^{j-i}i^k\frac{n!}{(n-j)!}(1+n)^{n-j}&(\text{斯特林數拆開})\\ &=\sum_{j=1}^k\binom{n}{j}\sum_{i=0}^j\binom{j}{i}(-1)^{j-i}i^k(1+n)^{n-j}\\ &=\sum_{i=1}^ki^k(-1)^i\sum_{j=i}^k\binom{n}{j}\binom{j}{i}(-1)^{j}(1+n)^{n-j}\\ &=(1+n)^n\sum_{i=1}^ki^k(-1)^i\sum_{j=i}^k\binom{n}{j}\binom{j}{i}(\frac{-1}{1+n})^{j}\\ &=(1+n)^n\sum_{i=1}^ki^k(-1)^i\sum_{j=i}^k\frac{n!j!}{(n-j)!j!i!(j-i)!}(\frac{-1}{1+n})^{j}\\ &=(1+n)^n\sum_{i=1}^ki^k(-1)^i\binom{n}{i}\sum_{j=i}^k\binom{n-i}{j-i}(\frac{-1}{1+n})^{j}\\ &=(1+n)^n\sum_{i=1}^ki^k\binom{n}{i}(\frac{1}{1+n})^{i}\sum_{j=0}^{k-i}\binom{n-i}{j}(\frac{-1}{1+n})^{j}\\ \end{aligned}\]

\(f_i=\sum_{j=0}^{k-i}\binom{n-i}{j}(\frac{-1}{1+n})^{j}\)

那麼:

\[\begin{aligned} f_i-f_{i+1}&=\sum_{j=0}^{k-i}\binom{n-i}{j}(\frac{-1}{1+n})^{j}-\sum_{j=0}^{k-i-1}\binom{n-i-1}{j}(\frac{-1}{1+n})^{j}\\ &=\binom{n-i}{k-i}(\frac{-1}{1+n})^{k-i}+\sum_{j=1}^{k-i-1}\binom{n-i-1}{j-1}(\frac{-1}{1+n})^{j}\\ &=\binom{n-i}{k-i}(\frac{-1}{1+n})^{k-i}+\sum_{j=0}^{k-i-2}\binom{n-i-1}{j}(\frac{-1}{1+n})^{j+1}\\ &=\binom{n-i}{k-i}(\frac{-1}{1+n})^{k-i}+f_{i+1}\times \frac{-1}{1+n}-\binom{n-i-1}{k-i-1}(\frac{-1}{1+n})^{k-i}\\ &=\binom{n-i-1}{k-i}(\frac{-1}{1+n})^{k-i}+f_{i+1}\times \frac{-1}{1+n}\\ \end{aligned}\]

所以:

\[\begin{aligned} f_i=\binom{n-i-1}{k-i}(\frac{-1}{1+n})^{k-i}+f_{i+1}(1+\frac{-1}{1+n}) \end{aligned}\]

遞推即可。

發現上面所有的東西都可以線性處理。

時間複雜度:\(O(k)\)

Code

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

#define fro(i, x, y) for (int i = (x); i <= (y); i++)
#define pre(i, x, y) for (int i = (x); i >= (y); i--)

typedef long long i64;

const int N = 1e6 + 10;
const int mod = 998244353;

int n, k, ct;
int r, num, sum, ans;
int f[N], iv[N], fc[N], vs[N], pr[N], sm[N];

inline i64 power(i64 x, i64 y) {
  i64 res = 1;
  while (y) {
    if (y & 1) res = res * x % mod;
    x = x * x % mod, y /= 2;
  }
  return res;
}
inline i64 C1(int x, int y) {
  if (x < 0 || y < 0 || x - y < 0) return 0;
  while (r < x) ++r, num = 1ll * num * r % mod;
  return 1ll * num * iv[y] % mod;
}
inline i64 C2(int x, int y) {
  if (x < 0 || y < 0 || x - y < 0) return 0;
  return 1ll * (sum = 1ll * sum * (n - y + 1) % mod) * iv[y] % mod;
}

signed main() {
  ios::sync_with_stdio(0), cin.tie(0);
  cin >> n >> k;
  i64 p1 = mod - power(1 + n, mod - 2);
  i64 p2 = mod - p1;
  fc[0] = 1;
  fro(i, 1, k) fc[i] = 1ll * fc[i - 1] * i % mod;
  iv[k] = power(fc[k], mod - 2);
  pre(i, k, 1) iv[i - 1] = 1ll * iv[i] * i % mod;
  r = n - k, sum = 1, num = n - k;
  if (n > k) {
    f[k] = 1;
    for (int i = k - 1, pw = p1; i >= 0; i--, pw = p1 * pw % mod) {
      f[i] = (f[i + 1] * (p1 + 1) + C1(n - i - 1, k - i) * pw) % mod;
    }
  } else {
    i64 p = mod + 1 - p2; f[n] = 1;
    for (int i = n - 1; i >= 1; i--) {
      f[i] = f[i + 1] * p % mod;
    }
  }
  sm[1] = 1;
  fro(i, 2, k) {
    if (vs[i] == 0) pr[++ct] = i, sm[i] = power(i, k);
    for (int j = 1; j <= ct && pr[j] * i <= k; j++) {
      vs[pr[j] * i] = 1;
      sm[pr[j] * i] = 1ll * sm[pr[j]] * sm[i] % mod;
      if (i % pr[j] == 0) break;
    }
  }
  for (int i = 1, pw = p2; i <= k; i++, pw = p2 * pw % mod) {
    i64 val = sm[i];
    val = val * C2(n, i) % mod;
    val = val * pw % mod;
    ans = (ans + f[i] * val) % mod;
  }
  ans = ans * power(1 + n, n) % mod;
  cout << (ans % mod + mod) % mod << "\n";
  return 0;
}