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

\[\begin{aligned} &\sum_{k=0}^n f(k) x^k \binom{n}{k} \\ =&\sum_{i=0}^m a_i\sum_{k=0}^n k^i x^k \binom{n}{k} \\ =&\sum_{i=0}^m a_i\sum_{k=0}^nx^k \binom{n}{k} \sum_{j=0}^i \binom{k}{j} \begin{Bmatrix}i \\ j\end{Bmatrix}j! \\ =&\sum_{i=0}^m a_i \sum_{j=0}^i \begin{Bmatrix}i \\ j\end{Bmatrix}j! \binom{n}{j}\sum_{k=0}^nx^k\binom{n-j}{k-j} \\ =&\sum_{i=0}^m a_i \sum_{j=0}^i \begin{Bmatrix}i \\ j\end{Bmatrix}j! \binom{n}{j}\sum_{k=0}^{n-j}x^{k+j}\binom{n-j}{k}\\ =&\sum_{i=0}^m a_i \sum_{j=0}^i \begin{Bmatrix}i \\ j\end{Bmatrix}j! \binom{n}{j} x^j\sum_{k=0}^{n-j}x^k\binom{n-j}{k} \\ =&\sum_{i=0}^m a_i \sum_{j=0}^i \begin{Bmatrix}i \\ j\end{Bmatrix}j! \binom{n}{j} x^j(x+1)^{n-j} \\ =&\sum_{i=0}^m a_i \sum_{j=0}^i \begin{Bmatrix}i \\ j\end{Bmatrix}n^{\underline{j}} x^j(x+1)^{n-j} \\ \end{aligned}\]

预处理出 第二类斯特林数 和 \(n\) 的下降幂 后可以 \(\mathcal O(m^2 \log n)\) 计算。

#include <cstdio>
#include <vector>
using namespace std;

const int MAXK = 1000; int Mod;
int Add( int x , int y ) { x += y; return x >= Mod ? x - Mod : x; }
int Sub( int x , int y ) { x -= y; return x < 0 ? x + Mod : x; }
int Mul( int x , int y ) { return 1ll * x * y % Mod; }
int Qkpow( int x , int po ) { int Ans = 1; for( ; po ; po >>= 1 , x = Mul( x , x ) ) if( po & 1 ) Ans = Mul( Ans , x ); return Ans; }
int dn[ MAXK + 5 ] , S2[ MAXK + 5 ][ MAXK + 5 ];

int n , m , x , a[ MAXK + 5 ];
void Init() {
    dn[ 0 ] = 1;
    for( int i = 1 ; i <= MAXK ; i ++ ) dn[ i ] = Mul( dn[ i - 1 ] , n - i + 1 );
    S2[ 0 ][ 0 ] = 1;
    for( int i = 1 ; i <= MAXK ; i ++ ) {
        S2[ i ][ 0 ] = 0;
        for( int j = 1 ; j <= i ; j ++ ) S2[ i ][ j ] = Add( S2[ i - 1 ][ j - 1 ] , Mul( j , S2[ i - 1 ][ j ] ) );
    }
}

int main( ) {
    scanf("%d %d %d %d",&n,&x,&Mod,&m); Init();
    for( int i = 0 ; i <= m ; i ++ ) scanf("%d",&a[ i ]);

    int Ans = 0;
    for( int i = 0 ; i <= m ; i ++ ) {
        int tmp = 0;
        for( int j = 0 ; j <= i ; j ++ )
            tmp = Add( tmp , Mul( Mul( S2[ i ][ j ] , dn[ j ] ) , Mul( Qkpow( x , j ) , Qkpow( x + 1 , n - j ) ) ) );
        Ans = Add( Ans , Mul( a[ i ] , tmp ) );
    }
    printf("%d\n", Ans );
    return 0;
}
posted @ 2021-03-31 17:24  chihik  阅读(38)  评论(0编辑  收藏  举报