• LOJ#3300. 「联合省选 2020 A」组合数问题 第二类斯特林数


    考场上忘了第二类斯特林数公式,过于智障,这里再重新推一遍.  

    首先,$S(i,j)$ 表示的意义是将 $i$ 个不同的球放入 $j$ 个相同的盒子中的方案数,且盒子不能为空.    

    那么有 $S(i,j)=S(i-1,j-1)+S(i-1,j) imes j$ 分别表示新开一个盒子/放入之前的盒子.         

    然后很多题会有 $sum i^x$ 这种式子,这里 $i$ 的枚举范围很大,但是 $x$ 不大,所以用第二类斯特林数转化为 $O(x)$ 的做法
    $Rightarrow n^m=sum_{i=0}^{min(n,m)} inom{n}{i} i! S(m,i)$.    

     组合意义是 $n^m$ 表示将 $m$ 个不同的球放入 $n$ 个不同盒子的方案数,那么我们就枚举哪些盒子里装了球.      

    原题:求$sum_{k=0}^{n} f(k) x^k inom{n}{k}$.   

    其中 $f(x)$ 是一个 $m leqslant 10^3$ 的多项式.   

    考虑枚举 $f(x)$ 中每一个系数的贡献,有 $sum_{i=0}^{m} a_{i} sum_{k=0}^{n} k^i x^k inom{n}{k}$ 

    这里 $k$ 很大,$i$ 很小,所以考虑将 $k^i$ 转化,得到 

    $sum_{i=0}^{m} a_{i} sum_{j=0}^{i} S(i,j) j! sum_{k=j}^{n} inom{k}{j} x^k inom{n}{k}$  

    后面那个组合数可以拆出来一个 $inom{n}{j}$ 然后用二项式定理逆战开就得到 

    $sum_{i=0}^{m} a_{i} sum_{j=0}^{i} S(i,j) n^{ underline{j}}x^j (x+1)^{n-j}$. 

    提前预处理阶乘和下降幂,时间复杂度为 $O(m^2)$.  

    code:  

    #include <cstdio>  
    #include <cstring>
    #include <algorithm>   
    #define N 2004
    #define ll long long 
    #define setIO(s) freopen(s".in","r",stdin)
    using namespace std; 
    int n,x,mod,m;    
    int a[N],S[N][N],lw[N],pw[N],xi[N];     
    int qpow(int xr,int y) {     
        int tmp=1;  
        for(;y;y>>=1,xr=(ll)xr*xr%mod)   
            if(y&1) tmp=(ll)tmp*xr%mod;   
        return tmp;    
    }    
    void init() { 
        S[0][0]=1;   
        for(int i=1;i<N;++i) {  
            for(int j=1;j<=i;++j) { 
                S[i][j]=(ll)(S[i-1][j-1]+(ll)S[i-1][j]*j%mod)%mod;  
            }
        }        
    }
    int main() {  
        //setIO("input");  
        scanf("%d%d%d%d",&n,&x,&mod,&m);    
        init();   
        for(int i=0;i<=m;++i) { 
            scanf("%d",&a[i]); 
        }
        pw[0]=lw[0]=1;   
        for(int i=1;i<=m;++i) {
            lw[i]=(ll)lw[i-1]*(n-i+1)%mod;   
            pw[i]=(ll)pw[i-1]*x%mod;
            xi[i]=(ll)qpow((x+1)%mod,n-i);          
        }   
        xi[0]=qpow((x+1)%mod,n);    
        int ans=0;  
        for(int i=0;i<=m;++i) {    
            int tmp=0;   
            for(int j=0;j<=i;++j) { 
                (tmp+=(ll)S[i][j]*lw[j]%mod*pw[j]%mod*xi[j]%mod)%=mod;  
            } 
            (ans+=(ll)tmp*a[i]%mod)%=mod;  
        } 
        printf("%d
    ",ans);  
        return 0; 
    }
    

      

  • 相关阅读:
    day3-课堂笔记
    day2-作业及答案
    2016年11月19日一周工作知识点总结
    2016年11月19日一周工作知识点总结
    使用JDK开发WebService
    使用JDK开发WebService
    Java WebService 简单实例
    Java WebService 简单实例
    BigDecimal不整除的一个异常java.lang.ArithmeticException
    2016年11月13日周工作知识点总结
  • 原文地址:https://www.cnblogs.com/guangheli/p/13352895.html
Copyright © 2020-2023  润新知