[学习笔记] 分拆数的几种求法
其他
2020-04-10 10:37:19
阅读次数: 0
问题
- 令
fn 表示将
n 进行分拆的方案数。
- 例如,
1+1+1+1=1+1+2=1+3=2+2=4 ,所以
f4=5 。
- 给出
n≤105(n≤105),求
f1,f2,...,fn 对
998244353 取模。
算法一
- 考虑根号分治,设
S=n
。
- 对于
>S 的数,设
gi,j 表示选了
i 个数总和为
i(S+1)+j 的方案数,转移有两种:
- 新加入一个数,初始值为
S+1:
gi,j+=gi−1,j;
- 给之前选的所有数
+1
:
gi,j+=gi,j−i。
- 不难发现,这样转移对于每一种拆分都有唯一的构造方式,并且第一维只有
O(n
) 级别,时间复杂度
O(nn
)。
- 求出
>S 的数的
DP 数组后,对于
≤S 的数,暴力背包
DP 即可,总的时间复杂度
O(nn
)。
- 这应该是最为通用的做法,常数也比较小。
算法二
- 令
f0=1,考虑
fi 的生成函数
F(x)=i=0∑∞fixi=i=1∏∞1−xi1=exp(i=1∑∞ln1−xi1)
- 注意到
ln1−xi1=∫(1−xi)(1−xi1)′dx=j=1∑∞xij−j=2∑∞jj−1xij=j=1∑∞jxij
- 所以
F(x)=exp(i=1∑∞j=1∑∞jxij)
- 可以
O(nlnn) 预处理出内部系数,再
exp 回去。
- 总的时间复杂度
O(nlogn)。
算法三
- 还是算法二中的生成函数,由
五边形数定理
得:
ϕ(x)=i=1∏∞(1−xi)=1+k=1∑∞(−1)kx2k(3k−1)
- 这里直接引用 visit_world博客中的证明。
- 由于
ϕ(x)F(x)=1,可以直接多项式求逆,时间复杂度
O(nlogn)。
- 还有一种更简单的方法, 注意到
ϕ(x)(modxn+1) 中系数不为
0 的项只有
O(n
) 个,暴力模拟求逆即可,时间复杂度
O(nn
)。
发布了116 篇原创文章 ·
获赞 136 ·
访问量 3万+
转载自blog.csdn.net/bzjr_Log_x/article/details/104276776