• LOJ 6089 小 Y 的背包计数问题 解题报告 (动态规划)


    #6089. 小 Y 的背包计数问题

    题意

    有一个容量为 (n) 的背包 (( n le 10^5)).

    (n) 种物品, 第 (i) 种物品有 (i) 个, 体积为 (i).

    求将背包装满的方案数.

    思路

    直接多重背包肯定不行, 加前缀和优化也有 (n^2).

    考虑到, 体积大于 (sqrt{n}) 的物品一定不会用完, 所以相当于一个无限背包,

    对体积小于 (sqrt{n}) 的物品, 做一个前缀和优化的多重背包就行了, 复杂度为 (O(n)).

    对于体积大于等于 (sqrt{n}) 的物品, 直接做无限背包肯定也不行,

    考虑到这些物品有一个性质 : 它们的体积是递增的, 那我们可以把无限背包的过程转化为以下两个操作,

    1. 往背包里加入一个体积为 (sqrt{n}) 的物品.
    2. 把背包里所有物品的体积都 +1.

    无限背包的过程其实就相当于维护了一个递增序列, 而上述的两个操作也可以构造出所有递增序列, 所以它们是等价的.

    所以, 我们设 (f[i][j]) 为往背包中放了 (i) 个物品, 总体积为 (j) 的方案数,

    1. (f[i][j]+=f[i-1][j-sqrt{n}])
    2. (f[i][j]+=f[i][j-1])

    分别代表 往背包内加一个体积为 (sqrt{n}) 的物品 和 把背包内所有物品体积 +1.

    由于这些物品的体积都大于 (sqrt{n}), 所以最多只能放 (sqrt{n}) 个物品, 因此复杂度为 (O(nsqrt{n})).

    代码

    #include<bits/stdc++.h>
    using namespace std;
    const int _=320+7;
    const int __=1e5+7;
    const int mod=23333333;
    int n,t,f[__],sum[__],g[_][__],ans;
    int main(){
      //freopen("x.in","r",stdin);
      cin>>n; t=ceil(sqrt(n));
      f[0]=1; sum[0]=1;
      for(int i=1;i<t;i++){
        for(int j=i;j<=n;j++) f[j]=(f[j]+f[j-i])%mod;
        for(int j=n;j>=(i+1)*i;j--) f[j]=((f[j]-f[j-(i+1)*i])%mod+mod)%mod;
      }
      g[0][0]=1;
      for(int i=1;i<=t;i++)
        for(int j=0;j<=n;j++){
          if(j>=i) g[i][j]=(g[i][j]+g[i][j-i])%mod;
          if(j>=t) g[i][j]=(g[i][j]+g[i-1][j-t])%mod;
        }
      for(int i=1;i<=t;i++)
        for(int j=0;j<=n;j++)
          g[0][j]=(g[0][j]+g[i][j])%mod;
      for(int j=0;j<=n;j++)
        ans=(ans+(long long)f[j]*g[0][n-j]%mod)%mod;
      printf("%d
    ",ans);
      return 0;
    }
    
    
  • 相关阅读:
    数据结构(三)栈与递归
    机器学习(二)------ 回归
    数据结构(二)线性表
    数据结构(一)数据结构基础
    机器学习 (一)------分类
    操作系统概述
    NumPy函数库基础
    总线与输入输出子系统
    FT VIEW SE高效开发之全局对象
    STUDIO 5000 V32新CRACK和新功能
  • 原文地址:https://www.cnblogs.com/BruceW/p/12181249.html
Copyright © 2020-2023  润新知