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

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

分析

我们考虑将式子。

\[\sum_{k=0}^{n}f(k)*x^k*\binom{n}{k} \]

其中f(k)是一个多项式,我们考虑其中某一个单项式

\[k^i*\binom{n}{k}*x^k \]

这里,有一个非常常用的小技巧。

\[x^{\underline{m}}*\binom{n}{k} = \binom{n-m}{k-m}n^{\underline{m}} \]

一次我们考虑将\(f(k)=\sum_{i=0}^{m}a_ik^i\)转化为下降幂多项式\(f(k)=\sum_{i=0}^{m}b_ix^{\underline{i}}\)

则式子就变为了。

\[\sum_{k=0}^{n}\sum_{i=0}^{m}b_ik^{\underline{i}}*x^k*\binom{n}{k} = \sum_{i=0}^{m}b_in^{\underline{i}}\sum_{k=0}^{n}\binom{n-i}{k-i}x^k \]

此时我们将后面进行二项式展开

\[\sum_{i=0}^{m}b_in^{\underline{i}}\sum_{k=0}^{n-i}\binom{n-i}{k}x^{k+i} = \sum_{i=0}^{m}b_in^{\underline{i}}x^i(x+1)^{n-i} \]

接下来就是最后一个问题了,如何将一个普通多项式转化为下降沿多项式

这个问题有\(O(nlogn)\)的解法,但是本题不用这么麻烦,可以直接用\(O(n^2)\)的方法。

我们来推导一下。

我们知道

\[x^n=\sum_{i=0}^{n}S(n,i)x^{\underline{i}} \]

因此,当我们带入并交换求和次序时,可以得到。

\[\sum_{i=0}^{m}a_ik^i = \sum_{i=0}^{m}a_i\sum_{j=0}^{i}S(i,j)k^{\underline{j}} \\=\sum_{i=0}^{m}k^{\underline{i}}\sum_{j=i}^{m}S(j,i)a_j \]

也就是说

\[b_i = \sum_{j=i}^{m}S(j,i)a_j \]

结束啦。

AC_code

#include<bits/stdc++.h>
#define ios ios::sync_with_stdio(false); cin.tie(0), cout.tie(0)
using namespace std;

const int N = 1010;

int S[N][N];
int n,x,p,m;

void init(int n)
{
    S[0][0] = 1;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            S[i][j] = (1ll*S[i-1][j-1] + 1ll*j*S[i-1][j]%p)%p;
}

int ksm(int a,int b)
{
    int res = 1;
    while(b)
    {
        if(b&1) res = 1ll*res*a%p;
        a = 1ll*a*a%p;
        b >>= 1;
    }
    return res;
}

int main()
{
    ios;
    cin>>n>>x>>p>>m;
    init(m);
    vector<int> a(m+1),b(m+1),xpow(m+1),fact(m+1),x1pow(m+1);
    fact[0] = xpow[0] = 1;
    for(int i=1;i<=m;i++)
    {
        fact[i] = 1ll*fact[i-1]*(n-i+1)%p;
        xpow[i] = 1ll*xpow[i-1]*x%p;
    }
    x1pow[m] = ksm((x+1)%p,n-m);
    for(int i=m-1;i>=0;i--)
        x1pow[i] = 1ll*x1pow[i+1]*(x+1)%p;
    for(int i=0;i<=m;i++) cin>>a[i];
    for(int i=0;i<=m;i++)
        for(int j=i;j<=m;j++)
            b[i] = (1ll*b[i] + 1ll*S[j][i]*a[j]%p)%p;
    int ans = 0;
    for(int i=0;i<=m;i++)
        ans = (1ll*ans + 1ll*b[i]*fact[i]%p*xpow[i]%p*x1pow[i]%p)%p;
    cout<<ans<<'\n';
    return 0;
}
posted @ 2022-09-20 21:56  艾特玖  阅读(28)  评论(0)    收藏  举报