整数拆分
参考资料
题目大意
给定 \(n\),将其拆分成若干正整数(可重复)之和,不区分顺序,求方案数。
解题思路
\(O(n^2)\)
法一:
定义 \(f(i,j)\) 表示考虑前 \(1\sim i\),和为 \(j\) 的方案数,转移方程是:\(f(i,j)\gets f(i-1,j)+f(i-1,j-k\times i)\),这就相当于完全背包。
法二:
定义 \(f(i,j)\) 表示当前选了 \(i\) 个数,和为 \(j\) 的方案数,转移就是 \(f(i,j)\gets f(i,j-i)+f(i-1,j-1)\),可以画图理解一下。
\(O(n \sqrt n)\)
对应题目: P6189 [NOI Online #1 入门组] 跑步
考虑根号分治,\(B=\sqrt n\),对于 \(i\le B\) 的数采用 \(O(n^2)\) 的法一,对于 \(i\ge B\) 的树采用法二,只不过状态转移方程稍微改一改。
code
b=sqrt(n)+1;
f[0]=g[0][0]=h[0]=1;
for(int i=1;i<b;i++){
for(int j=i;j<=n;j++)
f[j]=(f[j]+f[j-i])%mod;
}
for(int i=1;i<=n/b;i++){
for(int j=i;j<=n;j++){
g[i][j]=g[i][j-i];
if(j>=b) g[i][j]=(g[i][j]+g[i-1][j-b])%mod;
}
for(int j=i;j<=n;j++) h[j]=(h[j]+g[i][j])%mod;
}
int ans=0;
for(int i=0;i<=n;i++) ans=(ans+1ll*f[i]*h[n-i]%mod)%mod;
\(O(n\log n)\)
生成函数,不太会,待补。

浙公网安备 33010602011771号