区间dp经典题
题目描述
AC代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| #include <bits/stdc++.h> using namespace std; const int N = 1e9+7;
long long int f[1001][1001]; int n; int main() { scanf("%d", &n); for (int i = 0; i <= n; i ++) { f[i][0] = 1; } for(int i = 1; i <= n; ++i) { for(int j = 0; j <= n; ++j) { f[i][j] = f[i-1][j] % N; if(j >= i) f[i][j] = (f[i][j] + f[i][j-i]) % N; } } printf("%d", f[n][n]); return 0; }
|
相当于是完全背包问题,重要的还是需要耐心推导表达式。
还有另一种思路:f[i][j]
表示的是总和是i,恰好表示成j个数的方案。
那么可以把f[i][j]
的集合划分成两个部分,一个是其中任意一个数为1的,一个是其中任意一一个数都严格大于1的。
那么任意一个数都大于1的集合正好与f[i-1][j-1]
是一一对应的。
任意一个数都严格大于1的集合与f[i-j][j]
也是一一对应的。
因此有状态转移式为:f[i][j]=f[i-1][j-1]+f[i-j][j]
。