居然是读阈(yu第四声)值…
对于大小
≤n√
的物品做多重背包(前缀和优化
O(n)
)
对于大小
≥n√
的物品完全背包魔改一下:
g[i][j]表示用i个物品体积为j的方案数g[i][j]
g[i][j]=g[i][j−i]+g[i−1][j−n√−1](前i个物品体积都加1,加入一个体积为(n√+1)的物品)
最后合并一下
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#define P 23333333
#define N 100000
#define LL long long
using namespace std;
int n,sz,lst,nw,t,f[2][N+5],g[2][N+5],ans;
int main() {
scanf("%d",&n);sz=(int)sqrt(n);
int lst=0,nw=1,s;f[0][0]=1;
for(int i=1;i<=sz;++i,lst^=1,nw^=1) {
memset(f[nw],0,sizeof(f[nw]));
for(int j=0;j<i;++j) {
s=0;
for(int k=0;k*i+j<=n;++k) {
s=(s+f[lst][k*i+j])%P;
f[nw][k*i+j]=s;
if(k>=i) s=(s-f[lst][(k-i)*i+j]+P)%P;
}
}
}
t=lst;ans=f[t][n];
g[0][0]=1,lst=0,nw=1;
for(int i=1;i<=sz;++i,lst^=1,nw^=1) {
memset(g[nw],0,sizeof(g[nw]));
for(int j=sz+1;j<=n;++j) {
g[nw][j]=g[lst][j-sz-1];
if(j>=i) g[nw][j]=(g[nw][j]+g[nw][j-i])%P;
}
for(int j=0;j<=n;++j) ans=(ans+(LL)f[t][j]*g[nw][n-j])%P;
}
printf("%d\n",ans);
}