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

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

数学蒟蒻再一次一败涂地。。。

我们知道:

\[{n \choose k}k^{\underline{m}}={n-m \choose k-m}n^{\underline{m}} \]

\(f(x)\)转下降幂,得\(f(x)=\sum_{i=0}^m b_i x^{\underline{i}}\)

\[\sum_{k=0}^n \sum_{i=0}^m b_i k^{\underline{i}} x^k {n \choose k}\\ =\sum_{k=0}^n \sum_{i=0}^m b_i x^k {n-i \choose k-i} n^{\underline{i}}\\ =\sum_{i=0}^m b_i n^{\underline{i}} \sum_{k=0}^n {n-i \choose k-i}x^k\\ =\sum_{i=0}^m b_i n^{\underline{i}} \sum_{k=0}^{n-i} {n-i \choose k} x^{k+i}\\ =\sum_{i=0}^m b_i n^{\underline{i}} x^i \sum_{k=0}^{n-i} {n-i \choose k} x^k \]

\[\sum_{k=0}^{n-i} {n-i \choose k} x^k\\ =\sum_{k=0}^{n-i} {n-i \choose k} x^k 1^{n-i-k}\\ =(x+1)^{n-i} \]

巨大的\(n\)就这么没了。。。

剩下一步就是普通幂转下降幂。

\[x^{\underline n}=\sum_{i=0}^n (-1)^{n-i} {n \brack i} x^i\\ a_i=\sum_{j=i}^n (-1)^{j-i} {j \brack i} b_j \]

一步斯特林反演:

\[b_i=\sum_{j=i}^n {j \brace i} a_i \]

\(O(m^2)\)求出第二类斯特林数,这道题就做完了。

\(Code:\)

#include<iostream>
#include<cstdio>
#include<algorithm>
#define N 1005
#define ll long long
using namespace std;
int n,x,p,m,a[N],b[N];
int ans=0,s2[N][N];
void Add(int &x,int y)
{
    x=(x+y)%p;
}
void Mul(int &x,int y)
{
    x=(ll)x*y%p;
}
int add(int x,int y)
{
    return (x+y)%p;
}
int mul(int x,int y)
{
    return (ll)x*y%p;
}
int ksm(int x,int y)
{
    int ans=1;
    while (y)
    {
        if (y & 1)
            Mul(ans,x);
        Mul(x,x);
        y >>=1;
    }
    return ans;
}
int main()
{
    scanf("%d%d%d%d",&n,&x,&p,&m);
    for (int i=0;i<=m;++i)
        scanf("%d",&a[i]);
    s2[0][0]=1;
    for (int i=1;i<=m;++i)
        for (int j=1;j<=i;++j)
            s2[i][j]=add(s2[i-1][j-1],mul(s2[i-1][j],j));
    for (int i=0;i<=m;++i)
        for (int j=i;j<=m;++j)
            Add(b[i],mul(s2[j][i],a[j]));
    int xs=1,xj=1;
    for (int i=0;i<=m;++i)
    {
        Add(ans,mul(b[i],mul(xj,mul(xs,ksm(x+1,n-i)))));
        Mul(xs,x),Mul(xj,n-i);
    }
    ans=(ans%p+p)%p;
    printf("%d\n",ans);
    return 0;
}
posted @ 2021-01-02 21:44  GK0328  阅读(59)  评论(0编辑  收藏  举报