【题目描述】
【思路】
d
p
[
i
]
[
j
]
表
示
数
字
i
被
划
分
成
j
个
互
不
相
同
的
数
字
之
和
的
方
案
数
,
那
么
dp[i][j] 表示数字i被划分成j个互不相同的数字之和的方案数,那么
dp[i][j]表示数字i被划分成j个互不相同的数字之和的方案数,那么
d
p
[
i
]
[
j
]
=
d
p
[
i
−
j
]
[
j
]
+
d
p
[
i
−
1
]
[
j
−
1
]
dp[i][j]=dp[i-j][j]+dp[i-1][j-1]
dp[i][j]=dp[i−j][j]+dp[i−1][j−1]
前
一
项
表
示
数
字
i
−
j
被
划
分
成
j
个
互
不
相
同
的
数
,
然
后
每
个
数
字
+
1
就
能
得
到
数
字
i
了
,
后
一
项
表
示
数
字
i
−
j
被
划
分
成
j
−
1
个
互
不
相
同
的
数
,
然
后
每
个
数
字
+
1
后
再
加
上
一
个
数
字
1
也
能
得
到
数
字
i
,
j
个
互
不
相
同
的
数
相
加
至
少
是
j
(
j
−
1
)
/
2
,
是
j
2
的
级
别
,
所
以
j
只
需
要
枚
举
到
n
的
数
量
级
就
可
以
了
前一项表示数字i-j被划分成j个互不相同的数,然后每个数字+1就能得到数字i了,后一项表示数字i-j被划分成j-1个互不相同的数,然后每个数字+1后再加上一个数字1也能得到数字i,j个互不相同的数相加至少是j(j-1)/2,是j^2的级别,所以j只需要枚举到\sqrt{n}的数量级就可以了
前一项表示数字i−j被划分成j个互不相同的数,然后每个数字+1就能得到数字i了,后一项表示数字i−j被划分成j−1个互不相同的数,然后每个数字+1后再加上一个数字1也能得到数字i,j个互不相同的数相加至少是j(j−1)/2,是j2的级别,所以j只需要枚举到n的数量级就可以了
#include<bits/stdc++.h>
using namespace std;
const int mod=1e9+7;
const int maxn=50005;
const int maxm=505;
int n;
int dp[maxn][maxm];
int main(){
scanf("%d",&n);
dp[0][0]=1;
for(int i=1;i<=n;++i){
for(int j=1;j<maxm;++j){
if(i>=j) dp[i][j]=((long long)dp[i-j][j]+dp[i-j][j-1])%mod;
}
}
long long ans=0;
for(int j=1;j<maxm;++j){
ans=(ans+dp[n][j])%mod;
}
printf("%lld\n",ans);
return 0;
}