题解 P6620【[省选联考 2020 A 卷] 组合数问题】

前置知识:https://www.cnblogs.com/caijianhong/p/18409103

题目描述

众所周知,小葱同学擅长计算,尤其擅长计算组合数。小葱现在希望你计算

\[\left(\sum_{k=0}^{n}f(k)\times x^k\times \binom{n}{k}\right)\bmod p \]

的值。其中 \(n\), \(x\), \(p\) 为给定的整数,\(f(k)\) 为给定的一个 \(m\) 次多项式 \(f(k) = a_0 + a_1k + a_2k^2 + \cdots + a_mk^m\)\(\binom{n}{k}\) 为组合数,其值为 \(\binom{n}{k} = \frac{n!}{k!(n-k)!}\)

对于所有测试数据:\(1\le n, x, p \le 10^9, 0\le a_i\le 10^9, 0\le m \le \min(n,1000)\)

solution

\(f(k)\) 转为下降幂形式 \(\sum_{i=0}^m b_ik^{\underline i}\)。则有

\[\begin{aligned} &=\sum_{k=0}^n\sum_{i=0}^mb_ik^{\underline i}x^k\binom n k\\ &=\sum_{k=0}^n\sum_{i=0}^mb_in^{\underline i}x^k\binom {n-i} {k-i}\\ &=\sum_{i=0}^mb_in^{\underline i}\sum_{k=0}^nx^k\binom {n-i} {k-i}\\ &=\sum_{i=0}^mb_in^{\underline i}x^i\sum_{k=0}^{n-i}x^k\binom {n-i} {k}\\ &=\sum_{i=0}^mb_in^{\underline i}x^i(1+x)^{n-i} \end{aligned} \]

足以计算。依实现,可以 \(O(m^2\log n)\)\(O(m^2)\)

code

#include <bits/stdc++.h>
using namespace std;
#ifdef LOCAL
#define debug(...) fprintf(stderr, ##__VA_ARGS__)
#else
#define endl "\n"
#define debug(...) void(0)
#endif
using LL = long long;
template <class T>
using must_int = enable_if_t<is_integral<T>::value, int>;
template <int id>
struct modint {/*{{{*/
  static int mod;
  static unsigned umod;
  static void setmod(int p) { mod = umod = p; }
  unsigned v;
  modint() : v(0) {}
  template <class T, must_int<T> = 0>
  modint(T x) {
    x %= mod;
    v = x < 0 ? x + mod : x;
  }
  modint operator+() const { return *this; }
  modint operator-() const { return modint() - *this; }
  friend int raw(const modint &self) { return self.v; }
  friend ostream& operator<<(ostream& os, const modint &self) { 
    return os << raw(self); 
  }
  modint &operator+=(const modint &rhs) {
    v += rhs.v;
    if (v >= umod) v -= umod;
    return *this;
  }
  modint &operator-=(const modint &rhs) {
    v -= rhs.v;
    if (v >= umod) v += umod;
    return *this;
  }
  modint &operator*=(const modint &rhs) {
    v = 1ull * v * rhs.v % umod;
    return *this;
  }
  modint &operator/=(const modint &rhs) {
    assert(rhs.v);
    return *this *= qpow(rhs, mod - 2);
  }
  template <class T, must_int<T> = 0>
  friend modint qpow(modint a, T b) {
    modint r = 1;
    for (; b; b >>= 1, a *= a)
      if (b & 1) r *= a;
    return r;
  }
  friend modint operator+(modint lhs, const modint &rhs) { return lhs += rhs; }
  friend modint operator-(modint lhs, const modint &rhs) { return lhs -= rhs; }
  friend modint operator*(modint lhs, const modint &rhs) { return lhs *= rhs; }
  friend modint operator/(modint lhs, const modint &rhs) { return lhs /= rhs; }
  bool operator==(const modint &rhs) const { return v == rhs.v; }
  bool operator!=(const modint &rhs) const { return v != rhs.v; }
};/*}}}*/
template <int id>
unsigned modint<id>::umod;
template <int id>
int modint<id>::mod;
using mint = modint<-1>;
int n, m;
mint X, b[1010], S[1010][1010];
int main() {
#ifndef LOCAL
  cin.tie(nullptr)->sync_with_stdio(false);  
#endif
  cin >> n >> X.v >> mint::mod >> m;
  mint::setmod(mint::mod);
  X.v %= mint::mod;
  S[0][0] = 1;
  for (int i = 1; i <= m; i++) {
    S[i][0] = 0;
    for (int j = 1; j <= i; j++) S[i][j] = S[i - 1][j - 1] + S[i - 1][j] * j;
  }
  for (int i = 0; i <= m; i++) {
    int x;
    cin >> x;
    for (int j = 0; j <= i; j++) b[j] += S[i][j] * x;
  }
  mint ans = 0;
  mint now = 1;
  for (int i = 0; i <= m; i++) {
    ans += b[i] * now * qpow(X, i) * qpow(1 + X, n - i);
    now *= n - i;
  }
  cout << ans << endl;
  return 0;
}

posted @ 2024-08-11 21:24  caijianhong  阅读(44)  评论(0编辑  收藏  举报