博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Loj #6089. 小 Y 的背包计数问题
阅读量:4965 次
发布时间:2019-06-12

本文共 1322 字,大约阅读时间需要 4 分钟。

link : https://loj.ac/problem/6089

 

大致就是第i个物品有i个且每个的体积是i,问填满体积为N的背包的方案数。

 

首先可以发现的是 > sqrt(N) 的物品是用不完的,所以可以看成完全背包。

但直接完全背包的话因为复杂度是 O((N-sqrt(N))*N) 的 ,其实就是 O(N^2),肯定会挂。

但是我们考虑一个性质:最后背包中的物品最多只能有sqrt(N)件,并且每件的起始体积都是sqrt(N)+1。

所以我们就设 g[i][j] 为选了i件物品,总体积为j的方案数。

转移就是 g[i][j] = g[i-1][j-(sqrt(N)+1)] + g[i][j-i]  ,这就是考虑每次多加一个初始体积物品或者给每个物品都+1的体积。

因为这样能保证后加的物品最后的体积一定<=前加的,所以符合无序性,是正确的。

 

至于<=sqrt(N)的物品直接暴力多重背包就行了 (当然前提是对于每个物品你的多重背包复杂度是 O(N)的,就是对物品体积的同余系下相同的元素一起处理)

 

#include
#define ll long long#define maxn 100005using namespace std;const int ha=23333333;int now,pre,f[2][maxn],n,S;int g[2][maxn],block[maxn];inline int add(int x,int y){ x+=y; return x>=ha?x-ha:x;}inline void dp_big(){ g[0][0]=1,now=0,block[0]++; for(int i=1;i*S<=n;i++){ pre=now,now^=1; fill(g[now],g[now]+i,0); for(int j=i;j<=n;j++){ g[now][j]=g[now][j-i]; if(j>=S) g[now][j]=add(g[now][j],g[pre][j-S]); block[j]=add(block[j],g[now][j]); } }}inline void dp_small(){ now=0,f[0][0]=1; for(int i=1,res;i
=0) tmp=add(tmp,ha-f[pre][u-res]); f[now][u]=tmp; } }}inline void output(){ int ans=0; for(int i=0;i<=n;i++) ans=add(ans,f[now][i]*(ll)block[n-i]%ha); printf("%d\n",ans);}int main(){ scanf("%d",&n),S=sqrt(n)+1; dp_big(); dp_small(); output(); return 0;}

  

 

转载于:https://www.cnblogs.com/JYYHH/p/8524849.html

你可能感兴趣的文章
自动提交Git branch代码评审到Review Board系统
查看>>
javaoop_pst和rst和cst
查看>>
【转载】自定义地图数据瓦片化请求的一种实现方案
查看>>
Spring之FactoryBean
查看>>
ORACLE常用数值函数、转换函数、字符串函数
查看>>
IAAS、SAAS 和 PAAS 的区别、理解
查看>>
Java RMI详解
查看>>
idea设置条件断点
查看>>
6.【应急响应】Linux入侵排查思路
查看>>
windows32位系统 安装MongoDB
查看>>
C#中的扩展类的理解
查看>>
TypeScript--函数
查看>>
【转】谷歌大数据的三篇论文
查看>>
第三章编程练习题3.1
查看>>
删除重复数据只保留一条
查看>>
排序之快速排序(上)
查看>>
计算机端口大全
查看>>
如何使用BHO定制你的Internet Explorer浏览器
查看>>
Android中用文件初始化sqlite 数据库的文(一) (转)
查看>>
手写简化版SpringBoot
查看>>