[学习笔记] 分拆数的几种求法

  • 对分拆数的多种求法做了简单的整理。

问题

  • f n f_n 表示将 n n 进行分拆的方案数。
  • 例如, 1 + 1 + 1 + 1 = 1 + 1 + 2 = 1 + 3 = 2 + 2 = 4 1 + 1 + 1 + 1 = 1 + 1 + 2 = 1 + 3 = 2 + 2 = 4 ,所以 f 4 = 5 f_4 = 5
  • 给出 n 1 0 5 ( n 1 0 5 ) n \le 10^5(n \le 10^5) ,求 f 1 , f 2 , . . . , f n f_1, f_2, ..., f_n 998244353 998244353 取模。

算法一

  • 考虑根号分治,设 S = n S = \sqrt{n}
  • 对于 > S > S 的数,设 g i , j g_{i,j} 表示选了 i i 个数总和为 i ( S + 1 ) + j i(S+1) + j 的方案数,转移有两种:
    1. 新加入一个数,初始值为 S + 1 S + 1 g i , j + = g i 1 , j g_{i,j} += g_{i - 1, j}
    2. 给之前选的所有数 +1 g i , j + = g i , j i g_{i,j} += g_{i,j - i}
  • 不难发现,这样转移对于每一种拆分都有唯一的构造方式,并且第一维只有 O ( n ) \mathcal O( \sqrt{n}) 级别,时间复杂度 O ( n n ) \mathcal O(n \sqrt{n})
  • 求出 > S >S 的数的 DP \text{DP} 数组后,对于 S \le S 的数,暴力背包 DP \text{DP} 即可,总的时间复杂度 O ( n n ) \mathcal O(n \sqrt{n})
  • 这应该是最为通用的做法,常数也比较小。

算法二

  • f 0 = 1 f_0 = 1 ,考虑 f i f_i 的生成函数
    F ( x ) = i = 0 f i x i = i = 1 1 1 x i = exp ( i = 1 ln 1 1 x i ) \begin{aligned} F(x) &= \sum \limits_{i = 0}^{\infty}f_ix^i \\ &= \prod \limits_{i = 1}^{\infty} \frac{1}{1 - x^i}\\ &= \exp\left(\sum \limits_{i = 1}^{\infty} \ln \frac{1}{1-x^i}\right)\\ \end{aligned}
  • 注意到
    ln 1 1 x i = ( 1 x i ) ( 1 1 x i ) d x = j = 1 x i j j = 2 j 1 j x i j = j = 1 x i j j \begin{aligned} \ln \frac{1}{1 - x^i} &= \int (1 - x^i)\left(\frac{1}{1 - x^i}\right)' dx\\ &= \sum \limits_{j = 1}^{\infty}x^{ij} - \sum \limits_{j = 2}^{\infty}\frac{j - 1}{j}x^{ij}\\ &= \sum \limits_{j = 1}^{\infty}\frac{x^{ij}}{j}\\ \end{aligned}
  • 所以
    F ( x ) = exp ( i = 1 j = 1 x i j j ) \begin{aligned} F(x) = \exp\left(\sum \limits_{i = 1}^{\infty}\sum \limits_{j = 1}^{\infty} \frac{x^{ij}}{j}\right)\\ \end{aligned}
  • 可以 O ( n ln n ) \mathcal O(n \ln n) 预处理出内部系数,再 exp \exp 回去。
  • 总的时间复杂度 O ( n log n ) \mathcal O(n \log n)

算法三

  • 还是算法二中的生成函数,由 五边形数定理 得:
    ϕ ( x ) = i = 1 ( 1 x i ) = 1 + k = 1 ( 1 ) k x k ( 3 k 1 ) 2 \begin{aligned} \phi(x) = \prod \limits_{i = 1}^{\infty} (1 - x^i) = 1 + \sum \limits_{k = 1}^{\infty}(-1)^kx^{\frac{k(3k - 1)}{2}} \end{aligned}
  • 这里直接引用 visit_world博客中的证明
  • 由于 ϕ ( x ) F ( x ) = 1 \phi(x)F(x) = 1 ,可以直接多项式求逆,时间复杂度 O ( n log n ) \mathcal O(n \log n)
  • 还有一种更简单的方法, 注意到 ϕ ( x ) ( m o d    x n + 1 ) \phi(x)(\mod x^{n + 1}) 中系数不为 0 0 的项只有 O ( n ) \mathcal O(\sqrt{n}) 个,暴力模拟求逆即可,时间复杂度 O ( n n ) \mathcal O(n \sqrt{n})
发布了116 篇原创文章 · 获赞 136 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/bzjr_Log_x/article/details/104276776