题解:[省选联考 2020 A 卷] 组合数问题

题解——[省选联考 2020 A 卷] 组合数问题

题目描述

计算

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

\(1\le n, x, p \le 10^9, 0\le a_i\le 10^9, 0\le m \le \min(n,1000)\)

思路

其实思路并不难,只有最后一步有点小思维。

\( \begin{aligned} &\sum_{k=0}^{n}f(k)x^k\binom{n}{k} \\ &=\sum_{k=0}^{n}\sum_{i=0}^{m}a_ik^ix^k\binom{n}{k} \\ &=\sum_{i=0}^{m}a_i\sum_{k=0}^{n}x^k\binom{n}{k}\sum_{j=0}^{i}{\binom{k}{j}{i \brace j}j!} \\ &=\sum_{i=0}^{m}a_i\sum_{j=0}^{i}{i \brace j}j!\sum_{k=0}^{n}{\binom{k}{j}\binom{n}{k}x^k} \\ &=\sum_{i=0}^{m}a_i\sum_{j=0}^{i}\binom{n}{j}{i \brace j}j!\sum_{k=0}^{n}{\binom{n-j}{k-j}x^k} \\ &=\sum_{i=0}^{m}a_i\sum_{j=0}^{i}\binom{n}{j}{i \brace j}j!x^j\sum_{k=0}^{n}{\binom{n-j}{k-j}x^{k-j}} \\ &=\sum_{i=0}^{m}a_i\sum_{j=0}^{i}A_{n}^{j}{i \brace j}x^j(1+x)^{n-j} \end{aligned} \)

其实最后一步我还有一种十分诡谲的做法,但是太麻烦就不写了。

不过还有一个小技巧,尽管所有的数都缩到了 \(m\) 里,但是这个 \(A_{n}^{j}\) 并没有,但不过可以预处理出来每次 \(A_{n}^{j}=A_{n}^{j-1}(n-j+1)\) 就好了。

code
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
#include <bitset>
#include <set>
#include <map>
#include <cstdio>
#include <cassert>
#include <iomanip>

using namespace std;

#define lid id << 1
#define rid id << 1 | 1
#define emp emplace_back
#define endl '\n'
#define fi first
#define se second

const int N = 1e3 + 7;

#define int long long

using ll = long long;
using ld = long double;
using pii = pair <int, int>;

int a[N], s[N][N], mod;

int qpow(int x, int b)
{
    int res = 1;
    while (b)
    {
        if (b & 1) res = res * x % mod;
        x = x * x % mod;
        b >>= 1;
    }
    return res;
}

int A[N];

signed main()
{
    // freopen("data.in", "r", stdin); freopen("data.out", "w", stdout);
	ios :: sync_with_stdio(false), cin.tie(0), cout.tie(0);

    int n, x, m; cin >> n >> x >> mod >> m;
    s[0][0] = 1;
    for (int i = 1; i <= m; i++)
    {
        for (int j = 1; j <= m; j++)
        {
            s[i][j] = (s[i - 1][j - 1] + s[i - 1][j] * j) % mod;
        }
    }
    A[0] = 1;
    for (int i = 1; i <= m; i++) A[i] = A[i - 1] * (n - i + 1) % mod;
    int ans = 0, res = 0;
    for (int i = 0; i <= m; i++)
    {
        cin >> a[i];
        res = 0;
        for (int j = 0; j <= i; j++)
        {
            res += A[j] * s[i][j] % mod * qpow(x, j) % mod * qpow(1 + x, n - j) % mod;
            res %= mod;
        }
        ans += a[i] * res;
        ans %= mod;
    }
    cout << ans;

    return 0;
}
posted @ 2025-05-18 15:18  QEDQEDQED  阅读(23)  评论(1)    收藏  举报