就是那个分块的套路。小于等于
n−−√
直接暴力背包。大于
n−−√
可以发现物品最多取
n−−√
个,所以就用旋转体积背包那样搞。
总复杂度
O(nn−−√)
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long LL;
const int maxn=50005,MOD=1e9+7;
int n,f0[maxn],B,f[maxn][230],f1[maxn],ans;
int main(){
freopen("51nod1259.in","r",stdin);
freopen("51nod1259.out","w",stdout);
scanf("%d",&n); B=sqrt(n)+1;
f0[0]=1;
for(int i=1;i<=B-1;i++)
for(int j=i;j<=n;j++) (f0[j]+=f0[j-i])%=MOD;
f[B][1]=1;
for(int i=B;i<=n;i++)
for(int j=1;j<=B;j++){
(f[i][j]+=f[i-B][j-1])%=MOD;
if(i-j>=0) (f[i][j]+=f[i-j][j])%=MOD;
(f1[i]+=f[i][j])%=MOD;
}
ans=(f0[n]+f1[n])%MOD;
for(int i=1;i<=n-1;i++) (ans+=(LL)f0[i]*f1[n-i]%MOD)%=MOD;
printf("%d\n",ans);
return 0;
}