【背包+阈值优化】51Nod 1597 有限背包计数问题

来源:互联网 发布:java管理平台 编辑:程序博客网 时间:2024/06/15 00:22

题面在这里

显然,对于小于n的物品可以直接对每个背包大小记前缀和

对于大于n的物品直接改定义为“选了i个物品,背包大小为j”即可

很好转移吧……

示例程序:

#include<cstdio>#include<cmath>#include<cstring>typedef long long ll;const int maxn=100005,maxs=320,tt=23333333;int n,s,f[2][maxn],g[2][maxn],tem[maxn];inline void Madd(int &x,int y) {if ((x+=y)>=tt) x-=tt;}int main(){    scanf("%d",&n);s=sqrt(n);    f[0][0]=1;    for (int i=1;i<=s;i++){        memset(tem,0,sizeof(tem));        for (int j=0;j<=n;j++){            Madd(tem[j%i],f[i&1^1][j]);            f[i&1][j]=tem[j%i];            if (j-i*i>=0) Madd(tem[j%i],tt-f[i&1^1][j-i*i]);        }    }    g[0][0]=1;int ans=f[s&1][n];    for (int i=1;i<=s;i++){        for (int j=0;j<i;j++) g[i&1][j]=0;        for (int j=i;j<=n;j++){            g[i&1][j]=g[i&1][j-i];            if (j>s) Madd(g[i&1][j],g[i&1^1][j-s-1]);            Madd(ans,(ll)g[i&1][j]*f[s&1][n-j]%tt);        }    }    printf("%d",ans);    return 0;}
原创粉丝点击