9 ACwing 279 自然数拆分Lunatic版 题解
自然数拆分Lunatic版
题面
给定一个自然数 \(N\) ,要求把 \(N\) 拆分成若干个正整数相加的形式,参与加法运算的数可以重复
- 拆分方案不考虑顺序;
- 至少拆分成 2 个数的和。
求拆分的方案数 \(\bmod 2^{31}\) 的结果
\(1 \le N \le 4000\)
题解
完全背包板子,设 \(f(i,j)\) 表示考虑前 \(i\) 个数,从中选若干个,可以重复,和为 \(j\) 的方案数
转移 \(f(i,j) += f(i - 1, j - i)\) ,同样可以优化掉第一维,时间复杂度 \(O(N^2)\) ,内层循环正序枚举即可
code
注意一下 unsigned int
的范围是 \(0 \sim 2^{32} - 1\) 所以不能用溢出取模,要手动取模
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
using namespace std;
const int N = 4010;
const unsigned int mod = 2147483648u;
int n;
unsigned int f[N];
int main () {
cin >> n;
f[0] = 1;
for (int i = 1; i < n; i++) {
for (int j = i; j <= n; j ++) {
f[j] += f[j - i];
f[j] %= mod;
}
}
cout << f[n] << endl;
return 0;
}