【题目描述】
【思路】
dp[i][j]表示数字i被划分成j个互不相同的数字之和的方案数,那么dp[i][j] 表示数字i被划分成j个互不相同的数字之和的方案数,那么dp[i][j]表示数字i被划分成j个互不相同的数字之和的方案数,那么 dp[i][j]=dp[i−j][j]+dp[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,是j2的级别,所以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;
}