zoukankan      html  css  js  c++  java
  • 第一类和第二类斯特林数

    第一类斯特林数

    第一类斯特林数定义如下:

    (s_1(n,k))表示(n)个元素组成(k)个圆排列的方案数。

    其中(n)个元素的圆排列定义为(n)个元素围成一圈的排列,两个圆排列本质相同当且仅当两个圆排列以任意方式旋转之后相同。


    那么我们可以得到第一类斯特林数的递推公式:

    [s_1(n,k)=s_1(n-1,k-1)+(n-1)cdot s_1(n-1,k) ]

    这个很好理解,第一项是第(n)个元素单独组成一个圆排列,第二项是不单独组成,那么我可以把第(n)个元素放在任意一个元素的左边(右边),这里左边和右边其实是等价的。


    这样求出(s_1(n,k))时空复杂度都是(O(nk))的,但是我们还有更优秀的做法:

    考虑下面这个生成函数:

    [F(x)=prod_{i=0}^{n-1}(x+i) ]

    其中([x^k]F(x))就是(s_1(n,k))

    这个可以对照着前面的递推方程感性理解,基本上就是每乘一次((x+i))就表示从(s_1(n,k))转移到(s_1(n+1,k))

    那么我们就可以分治(FFT)优化到(O(nlog^2n))

    好像还有一种倍增的(O(nlog n))的做法先咕着以后再填。


    例题:

    [洛谷4609] [FJOI2016]建筑师,这个直接暴力递推就好了。

    [CF960G] Bandit Blues,这个需要分治(FFT)

    第二类斯特林数

    第二类斯特林数定义如下:

    (s_2(n,k))表示把(n)个不同的元素放到(k)个无差别的盒子的方案数。


    那么很显然我们可以得到递推式:

    [s_2(n,k)=s_2(n-1,k-1)+kcdot s_2(n-1,k) ]

    复杂度(O(nk))


    考虑一个比较有意思的东西,假设我们现在要算(s_2(n,k)),设(f(i))表示至少(i)个盒子空着的方案数,(g(i))表示恰好(i)个盒子空着的方案数。

    那么我们可以得到:

    [f(i)=sum_{j=i}^kinom{j}{i}g(j)=inom{k}{i}(k-i)^n ]

    对其广义容斥一下可得:

    [g(i)=sum_{j=i}^k(-1)^{j-i}inom{j}{i}inom{k}{j}(k-j)^n ]

    那么可以据此算出(s_2)

    [s_2(n,k)=g(0)=sum_{i=0}^k(-1)^iinom{k}{i}(k-i)^n ]

    注意到这是个卷积的形式,所以我们可以在(O(nlog n))的时间内求出(s_2(n,i))的每一项,这里每一项指的是对于给定的(n)(iin [1,n])的每一项。


    例题:

    洛谷P4091 [HEOI2016/TJOI2016]求和,solution是很久以前写的了,不是很好看...还是放这里吧:sol

  • 相关阅读:
    C# 二维数组 排列组合
    highcharts(数据可视化框架),ajax传递数据问题
    EasyPoi导入验证功能
    EasyPoi使用入门
    SSJ(Spring+springMVC+JPA)设置xml文件思路流程
    spring框架设置jdbc
    使用JDBC完成CRUD(增删改查)
    Java的数据类型(常量,变量)
    jdk8的安装与卸载
    Java的第一个你好世界
  • 原文地址:https://www.cnblogs.com/hbyer/p/10576904.html
Copyright © 2011-2022 走看看