zoukankan      html  css  js  c++  java
  • 斯特林数及斯特林反演

    此文章涉及到斯特林数性质及斯特林反演,例题总结与应用篇(Longrightarrow)点这里

    ({largecolor{SpringGreen}{历史小芝士}})

    在组合数学中,斯特林((Stirling))数可指两类数,第一类斯特林数和第二类斯特林数
    这些均由(18)世纪数学家(James Stirling)提出的,并在著作《(Methodous Differentialis)》中首次使用

    自此,斯特林数成为又一广泛运用到处理组合问题的一大利器

    ({largecolor{SpringGreen}{第一类斯特林数}})

    定义

    (egin{bmatrix}n\m end{bmatrix})表示(n)个元素分成(m)个环的方案数

    显然:$$egin{bmatrix}nm end{bmatrix}=egin{bmatrix}n-1m-1 end{bmatrix}+(n-1)*egin{bmatrix}n-1m end{bmatrix}$$

    理解:考虑从(n-1)个元素推过来,如果两个空环肯定是不符合的
    (~~~~~~~~~~)空一个环则单独成环,如果(n-1)的时候就没有空环就任意放在一个元素前

    性质

    • (n!=sumlimits_{i=0}^n egin{bmatrix}n\i end{bmatrix})

    理解:其实本质就是置换,一个环则为一组轮换,每种排列都会对应着唯一 一种置换

    • (x^{underline n}=sumlimits_{i=0}^n egin{bmatrix}n\i end{bmatrix}(-1)^{n-i}x^i\)

    归纳法:

    [egin{aligned}\ x^{underline {n+1}}&=(x-n)x^{underline n}\ &=(x-n)sumlimits_{i=0}^n egin{bmatrix}n\i end{bmatrix}(-1)^{n-i}x^i\ &=xsumlimits_{i=0}^{n} egin{bmatrix}n\i end{bmatrix}(-1)^{n-i}x^{i}-nsumlimits_{i=0}^n egin{bmatrix}n\i end{bmatrix}(-1)^{n-i} x^i\ &=sumlimits_{i=0}^{n} egin{bmatrix}n\i end{bmatrix}(-1)^{n-i}x^{i+1}-nsumlimits_{i=0}^{n+1} egin{bmatrix}n\i end{bmatrix}(-1)^{n-i} x^i\ &=sumlimits_{i=1}^{n+1} egin{bmatrix}n\i-1 end{bmatrix}(-1)^{n-i+1}x^{i}+nsumlimits_{i=0}^{n+1} egin{bmatrix}n\i end{bmatrix}(-1)^{n-i+1} x^i\ &=sumlimits_{i=1}^{n+1} ( egin{bmatrix}n\i-1 end{bmatrix} +n*egin{bmatrix}n\i end{bmatrix})(-1)^{n-i+1}x^{i}\ &=sumlimits_{i=1}^{n+1} egin{bmatrix}n+1\i end{bmatrix}(-1)^{n-i+1}x^{i}\ &=sumlimits_{i=0}^{(n+1)} egin{bmatrix}n+1\i end{bmatrix}(-1)^{(n+1)-i}x^{i}\ end{aligned}]

    • (x^{overline n}=sum_{i=0}^n egin{bmatrix}n\i end{bmatrix}x^i)

    证明类上,不再赘述

    求第一类斯特林数

    • [sum_{i=0}^n egin{bmatrix}n\i end{bmatrix}x^i=prod_{i=0}^{n-1}(x+i) ]

    (egin{array}{c c c}~&0&1&2&3&4\0&0&0&0&0&0\1&0&1&0&0&0\2&0&1&1&0&0\3&0&2&3&1&0\4&0&6&11&6&1end{array})

    其实把表刷出来就差不多了,可以理解为根据(egin{bmatrix}n\m end{bmatrix}=egin{bmatrix}n-1\m-1 end{bmatrix}+(n-1)*egin{bmatrix}n-1\m end{bmatrix})逐渐转移

    至此,我们可以通过分治(FFTO(nlog^2n))求出一行的第一类斯特林数

    • 还有一种类似于多项式求逆模式(O(nlogn))的方法

    [F(x)^n=prodlimits_{i=0}^{n-1}(x+i),F(x)^{2n}=F(x)^nF(x+n)^n ]

    考虑当我们求出(F(x)^n=sumlimits_{i=0}^{n}a_ix^i)

    [egin{aligned}\ F(x+n)^{n}&=sumlimits_{i=0}^{n}a_i(x+n)^i\ &=sumlimits_{i=0}^na_isumlimits_{j=0}^i{ichoose j}n^{i-j}x^j\ &=sumlimits_{i=0}^n(sumlimits_{j=i}^n {jchoose i}n^{j-i}a_j)x^i\ &=sumlimits_{i=0}^n(sumlimits_{j=i}^n frac{j!}{i!(j-i)!}n^{j-i}a_j)x^i\ &=sumlimits_{i=0}^n (i!)^{-1}x^i (sumlimits_{j=i}^n (frac{n^{j-i}}{(j-i)!})cdot (j!a_j))\ end{aligned}]

    我们通过左半部分系数能得到右半部分系数,再相乘一下就得到了总体的系数

    Code

    留有少量注释

    #include<bits/stdc++.h>
    typedef long long LL;
    const LL mod=998244353,g=3,maxn=1e6+9;
    inline LL Pow(LL base,LL b){
        LL ret(1);
        while(b){
            if(b&1) ret=ret*base%mod; base=base*base%mod; b>>=1;
        }return ret;
    }
    LL r[maxn];
    inline LL Fir(LL n){
        LL limit(1),len(0);
        while(limit<(n<<1)){
            limit<<=1; ++len;
        }
        for(LL i=0;i<limit;++i) r[i]=(r[i>>1]>>1)|((i&1)<<len-1);
        return limit;
    }
    inline void NTT(LL *a,LL n,LL type){
        for(LL i=0;i<n;++i) if(i<r[i]) std::swap(a[i],a[r[i]]);
        for(LL mid=1;mid<n;mid<<=1){
            LL wn(Pow(g,(mod-1)/(mid<<1))); if(type==-1) wn=Pow(wn,mod-2);
            for(LL R=mid<<1,j=0;j<n;j+=R)
                for(LL k=0,w=1;k<mid;++k,w=w*wn%mod){
                	LL x(a[j+k]),y(w*a[j+mid+k]%mod);
                	a[j+k]=(x+y)%mod; a[j+mid+k]=(x-y+mod)%mod;
                }
        }
        if(type==-1){
            LL ty(Pow(n,mod-2)); for(LL i=0;i<n;++i) a[i]=a[i]*ty%mod;
        }
    }
    LL T[maxn],F[maxn],H[maxn],G[maxn],fac[maxn],fav[maxn],tmp[maxn],sum[maxn],B[maxn];
    inline void Mul(LL n,LL *a,LL *b,LL *ans){
        LL limit(Fir(n));
        NTT(a,limit,1); NTT(b,limit,1);
        for(LL i=0;i<limit;++i) ans[i]=a[i]*b[i]%mod;
        NTT(ans,limit,-1);
    }
    inline void Solve(LL n,LL *a){
        if(!n){ a[0]=1; return; }
        if(n==1){ a[1]=1; return; }
        LL len(n/2);
        Solve(len,a);
        
        LL limit(Fir(len+1));
        for(LL i=0;i<=len;++i) F[i]=Pow(len,i)*fav[i]%mod;
        for(LL i=0;i<=len;++i) H[i]=fac[i]*a[i]%mod;
        for(LL i=0;i<=(len>>1);++i) std::swap(H[i],H[len-i]);
        for(LL i=len+1;i<limit;++i) F[i]=H[i]=0;
        NTT(F,limit,1); NTT(H,limit,1);
        for(LL i=0;i<limit;++i) G[i]=F[i]*H[i]%mod;
        NTT(G,limit,-1);
        for(LL i=0;i<=len;++i) tmp[i]=G[len-i]*Pow(fac[i],mod-2)%mod;//right
        
        Mul(len+1,a,tmp,B);//left * right
        for(LL i=0;i<=(len<<1);++i) a[i]=B[i];
        for(LL i=(len<<1)+1;i<=(len<<2);++i) a[i]=tmp[i]=0;
        
        if(n&1){
            for(LL i=0;i<n;++i) T[i]=a[i];
            for(LL i=1;i<=n;++i) a[i]=(T[i-1]+(n-1)*T[i]%mod)%mod;
        }
    }
    inline LL Get_c(LL n,LL m){
        return fac[n]*fav[m]%mod*fav[n-m]%mod;
    }
    LL n;
    LL ans[maxn];
    int main(){
        scanf("%lld",&n);
        fac[0]=fac[1]=1;
        for(LL i=2;i<=n;++i) fac[i]=fac[i-1]*i%mod;
        fav[n]=Pow(fac[n],mod-2);
        for(LL i=n;i>=1;--i) fav[i-1]=fav[i]*i%mod;
        Solve(n,ans);
    	for(LL i=0;i<=n;++i) printf("%lld ",ans[i]);printf("
    ");
    	return 0;
    }
    

    ({largecolor{SpringGreen}{第二类斯特林数}})

    定义

    (egin{Bmatrix}n\mend{Bmatrix})表示(n)个有区别的小球丢进(m)个无区别的盒子,无空盒子的方案数

    显然:$$egin{Bmatrix}nmend{Bmatrix}=egin{Bmatrix}n-1m-1end{Bmatrix}+m*egin{Bmatrix}n-1mend{Bmatrix}$$

    理解:考虑从(n-1)个小球推过来,如果两个空盒子肯定是不符合的
    (~~~~~~~~~~)空一个盒子则只能放到那个空盒子里面了,如果(n-1)的时候就没有空箱子就随便放

    性质

    [m^n=sum_{i=0}^{m}egin{Bmatrix}n\iend{Bmatrix}*i!*C(m,i) ]

    当然也可以写成:$$m^n=sumlimits_{i=0}^m egin{Bmatrix}niend{Bmatrix}*m^{underline i}$$

    到后面反演时我们会这样写:$$m^n=sumlimits_{i=0}^n egin{Bmatrix}niend{Bmatrix}*m^{underline i}$$
    看看后面的(m^{underline i})就懂了

    理解:(m^n)(n)个有区别的小球丢进(m)个有区别的盒子,允许空盒子
    (~~~~~~~~~~)枚举有效盒子的个数,再从(m)个盒子选(i)个盒子,然后(n)个小球丢进(i)个盒子

    转换到组合表示

    第二类斯特林数显然是和排列组合有关系的,转换过来:$$egin{Bmatrix}nmend{Bmatrix}=frac{1}{m!}sumlimits_{k=0}^m(-1)^kC(m,k)(m-k)^n$$

    理解:如果空箱子的情况我们也算进去,答案显然是(frac{m^n}{m!})
    (~~~~~~~~~~)反过来求第二类斯特林数,又得减掉这种情况:
    (~~~~~~~~~~)(k)个空盒子,然后小球放到其他的盒子里
    (~~~~~~~~~~)但最后我们求出来的答案为有区别的盒子,转换过来要(×frac{1}{m!})

    求第二类斯特林数

    大概都能猜到是卷积形式了吧,随手展开一下:

    [egin{aligned}\ egin{Bmatrix}n\mend{Bmatrix}&=frac{1}{m!}sumlimits_{k=0}^m(-1)^kfrac{m!}{k!(m-k)!}(m-k)^n\ &=sumlimits_{k=0}^mfrac{(-1)^k(m-k)^n}{k!(m-k)!}\ end{aligned}]

    至此,我们能实现(O(nlogn))求出(S(n))这一行的第二类斯特林

    第二类斯特林数与自然数幂的关系

    [egin{aligned}\ Sum(n)&=sumlimits_{i=0}^n i^k\ &=sumlimits_{i=0}^nsumlimits_{j=0}^kegin{Bmatrix}k\j end{Bmatrix}i^{underline j}\ &=sumlimits_{j=0}^kegin{Bmatrix}k\j end{Bmatrix}sumlimits_{i=0}^n i^{underline j}\ &=sumlimits_{j=0}^k egin{Bmatrix}k\j end{Bmatrix}j!sumlimits_{i=0}^nC_i^j\ &=sumlimits_{j=0}^k egin{Bmatrix}k\j end{Bmatrix}j!C_{n+1}^{j+1}\ &=sumlimits_{j=0}^k egin{Bmatrix}k\j end{Bmatrix} frac{(n+1)^{underline {j+1}}}{j+1}\ end{aligned}]

    关于(sumlimits_{i=0}^nC_i^j=C_{n+1}^{j+1})的理解:枚举(j+1)的右端点(i+1),则相当于从(i)个点中选(j)个点

    ({largecolor{SpringGreen}{斯特林反演}})

    定义

    斯特林反演:(f(n)=sumlimits_{k=0}^n egin{Bmatrix}n\k end{Bmatrix}g(k)Longleftrightarrow g(n)=sumlimits_{k=0}^n(-1)^{n-k}egin {bmatrix} n\k end{bmatrix}f(k))

    总结上面我们所推倒的性质

    • (x^{underline n}=sumlimits_{i=0}^n egin{bmatrix}n\i end{bmatrix}(-1)^{n-i}x^i,x^{overline n}=sum_{i=0}^n egin{bmatrix}n\i end{bmatrix}x^i)
    • (m^n=sumlimits_{i=0}^n egin{Bmatrix}n\iend{Bmatrix}*m^{underline i})

    补充

    [x^{underline n}=(-1)^n (-x)^{overline n},x^{overline n}=(-1)^n (-x)^{underline n} ]

    前置

    我们先证这个反转公式

    [egin{aligned}displaystyle sum_{k=m}^n (-1)^{n-k}egin{bmatrix}n\kend{bmatrix} egin{Bmatrix}k\mend{Bmatrix}=[m=n]\ sum_{k=m}^n (-1)^{n-k}egin{Bmatrix}n\kend{Bmatrix} egin{bmatrix}k\mend{bmatrix}=[m=n]end{aligned}]

    反转公式1

    [egin{aligned}\ m^{underline n}&=sumlimits_{i=0}^n egin{bmatrix}n\iend{bmatrix}(-1)^{n-i}m^i\ &=sumlimits_{i=0}^n egin{bmatrix}n\iend{bmatrix}(-1)^{n-i}sumlimits_{j=0}^i egin{Bmatrix}i\jend{Bmatrix}m^{underline j}\ &=sumlimits_{i=0}^n m^{underline i}sumlimits_{j=i}^n (-1)^{n-j} egin{bmatrix}n\jend{bmatrix} egin{Bmatrix}j\iend{Bmatrix}\ end{aligned}]

    反转公式2

    [egin{aligned}\ m^n&=sumlimits_{i=0}^negin{Bmatrix}n\iend{Bmatrix}m^{underline i}\ &=sumlimits_{i=0}^negin{Bmatrix}n\iend{Bmatrix}(-1)^i(-m)^{overline i}\ &=sumlimits_{i=0}^negin{Bmatrix}n\iend{Bmatrix}(-1)^isumlimits_{j=0}^i egin{bmatrix}i\jend{bmatrix}(-m)^j\ &=sumlimits_{i=0}^n m^isumlimits_{j=i}^n(-1)^{i-j} egin{Bmatrix}n\jend{Bmatrix}egin{bmatrix}j\iend{bmatrix}\ end{aligned}]

    推式

    已知:(g(n)=sumlimits_{k=0}^n(-1)^{n-k}egin {bmatrix} n\k end{bmatrix}f(k))

    [egin{aligned}\ f(n)&=sumlimits_{k=0}^n [k=n]f(k)\ &=sumlimits_{k=0}^nsumlimits_{j=k}^n egin {Bmatrix} n\j end{Bmatrix}egin {bmatrix} j\k end{bmatrix}(-1)^{j-k}f(k)\ &=sumlimits_{k=0}^n egin {Bmatrix} n\k end{Bmatrix}sumlimits_{j=0}^k (-1)^{k-j}egin {bmatrix} k\j end{bmatrix}f(j)\ &=sumlimits_{k=0}^n egin {Bmatrix} n\k end{Bmatrix}g(k)\ end{aligned}]

    ({largecolor{SpringGreen}{斯特林数应用}})

    总结

  • 相关阅读:
    TensorFlow实现LeNet5模型
    jmeter+influxdb+grafana性能测试可视化报告
    jmeter命令执行脚本
    jmeter JSON Extractor使用
    jmeter上传文件
    jenkins登录信息无效,忘记密码
    XML
    JMeter函数和变量
    jmeter配置CSV Data Set Config
    jmeter发送Query String Parameters格式参数报错
  • 原文地址:https://www.cnblogs.com/y2823774827y/p/10700231.html
Copyright © 2011-2022 走看看