51nod 1597 有限背包计数问题[dp][阈值]

来源:互联网 发布:java排序算法实现 编辑:程序博客网 时间:2024/06/07 14:32

居然是读阈(yu第四声)值…
对于大小n的物品做多重背包(前缀和优化O(n))
对于大小n的物品完全背包魔改一下:g[i][j]ijg[i][j]
g[i][j]=g[i][ji]+g[i1][jn1](i1,(n+1))
最后合并一下

#include<cstdio>#include<cmath>#include<algorithm>#include<cstring>#define P 23333333#define N 100000#define LL long longusing 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);}
原创粉丝点击