题目链接:点击这里
题目大意:
将
n
n
n 分为若干个不同整数的和,有多少种不同的划分方式
题目分析:
我们发现
n
n
n 最大是
5
e
5
5e5
5e5 ,而
5
e
5
5e5
5e5 最多能由不到
320
320
320 个不同的数字构成,这就确定了一个所用数字的上界
我们定义状态
d
p
[
i
]
[
j
]
dp[i][j]
dp[i][j] 表示用
i
i
i 个数构成
j
j
j 的方案数
初始状态为
d
p
[
0
]
[
0
]
=
1
dp[0][0]=1
dp[0][0]=1 表示用
0
0
0 个数构成
0
0
0 只有一种方案
状态转移方程为
d
p
[
i
]
[
j
]
=
d
p
[
i
]
[
j
−
i
]
+
d
p
[
i
−
1
]
[
j
−
i
]
dp[i][j]=dp[i][j-i]+dp[i-1][j-i]
dp[i][j]=dp[i][j−i]+dp[i−1][j−i]
本题最大的困难就是状态转移方程,在此给出该方程的解释:
d
p
[
i
]
[
j
−
i
]
dp[i][j-i]
dp[i][j−i] 表示用
i
i
i 个大于等于
2
2
2 的数拼成
j
j
j 的方案数(
j
−
i
j-i
j−i 是因为预留了
i
i
i 给选出来的
i
i
i 个数都加
1
1
1)
d
p
[
i
−
1
]
[
j
−
i
]
dp[i-1][j-i]
dp[i−1][j−i] 表示用
i
i
i 个数(其中含有
1
1
1)的数构成
j
j
j (
j
−
i
j-i
j−i 和上式同理,
i
−
1
i-1
i−1 是因为预留了一个
0
0
0 的位置使之加
1
1
1 后会变成
1
1
1)
具体细节见代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int inf=0x3f3f3f3f;
const int N=1e5+100;
const int mod = 1e9+7;
int n,dp[321][N],ans;
int main()
{
cin>>n;
dp[0][0] = 1;
for(int i = 1;i <= 320;i++)
for(int j = i;j <= n;j++)
dp[i][j] = (dp[i-1][j-i]+dp[i][j-i])%mod;
for(int i = 1;i <= 320;i++) ans = (ans+dp[i][n])%mod;
cout<<ans<<endl;
return 0;
}