• [loj6089]小Y的背包计数问题


    https://www.zybuluo.com/ysner/note/1285358

    题面

    (Y)有一个大小为(n)的背包,并且小(Y)(n)种物品。
    对于第(i)种物品,共有(i)个可以使用,并且对于每一个(i)物品,体积均为(i)
    求小(Y)把该背包装满的方案数为多少,答案对于(23333333)取模。
    定义两种不同的方案为:当且仅当至少存在一种物品的使用数量不同。

    • (nleq10^5)

    解析

    这个背包问题让我耳目一新啊。
    (idea)棒棒的。

    注意到题目中物品(i)(igeqsqrt n))的个数限制实际上是不存在的。
    所以可以把这个问题分为两个子问题:多重背包问题和完全背包问题。

    (f[i][v])表示前(i)个物品,总体积为(v)时的方案数。
    对于(ileqsqrt n):(多重背包问题)
    很显然有$$f[i][v]=sum_{j=1}^if[i-1][v-j*i]$$
    可以前缀和优化做到(O(nsqrt n))

    对于(igeqsqrt n):(完全背包问题)
    又注意到一个物品最多取(sqrt n)个。
    同样设个(g[i][v])表示方案数。
    可以认为我们要(DP)出一个和为(n),最小数至少(sqrt n+1)的不下降序列
    (序列中的数是物品体积)。
    转移有两种:

    • 在序列开头加入一个数(sqrt n+1)
    • 把序列中所有数(+1)

    则$$g[i][v]=g[i-1][v-sqrt n-1]+g[i][v-i]$$
    这个复杂度(O(n))
    最后讨论一下给前一个问题分配多少体积,后一个问题分配多少体积,统计答案即可。

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #define ll long long
    #define re register
    #define il inline
    #define max(a,b) (((a)>(b))?(a):(b))
    #define min(a,b) (((a)<(b))?(a):(b))
    #define fp(i,a,b) for(re int i=a;i<=b;i++)
    #define fq(i,a,b) for(re int i=a;i>=b;i--)
    using namespace std;
    const int N=2005,inf=2e9,mod=23333333;
    int n,f[N],g[350][N],s[N],ans=-inf,m;
    il ll gi()
    {
      re ll x=0,t=1;
      re char ch=getchar();
      while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
      if(ch=='-') t=-1,ch=getchar();
      while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
      return x*t;
    }
    int main()
    {
      n=gi();m=sqrt(n);
      f[0]=1;
      fp(i,1,m)
        {
          fp(j,0,i) s[j]=f[j];
          fp(j,i,n) s[j]=(f[j]+s[j-i])%mod;//前缀和
          fp(j,0,n)
    	{
    	  f[j]=s[j];
    	  if(j-i*(i+1)>=0) f[j]=(f[j]-s[j-i*(i+1)]+mod)%mod;//去掉不合法状态
    	}
        }
      g[0][0]=1;ans=f[n];
      fp(i,1,m)
        for(re int j=i*(m+1);j<=n;j++)
          {
    	g[i][j]=(g[i-1][j-m-1]+g[i][j-i])%mod;
    	(ans+=1ll*g[i][j]*f[n-j]%mod)%=mod;
          }
      printf("%d
    ",ans);
      return 0;
    }
    
  • 相关阅读:
    leetcode算法题(JavaScript实现)
    使用git submodule管理一个需要多个分立开发或者第三方repo的项目
    linux下从源代码安装git
    git项目实战常用workflow和命令
    如何在linux console中显示当前你在的branch?
    git plumbing 更加底层命令解析-深入理解GIT
    如何直接在github网站上更新你fork的repo?
    git remotes
    git和其他版本控制系统的区别
    Git server安装和配置
  • 原文地址:https://www.cnblogs.com/yanshannan/p/9668700.html
Copyright © 2020-2023  润新知