你有一个大小为n的背包,你有n种物品,第i种物品的大小为i,且有i个,求装满这个背包的方案数有多少
  两种方案不同当且仅当存在至少一个数i满足第i种物品使用的数量不同

 Input
  第一行一个正整数n
  1<=n<=10^5
 Output
  一个非负整数表示答案,你需要将答案对23333333取模

 
首先我们可以发现,令S=sqrt(n),那么对于大小大于S的物品,其实是用不完的,我们可以把他们的数量视为无限个

对于大小小于S的物品,我们可以令f[i][j]表示考虑了前i个物品,总大小为j的方案数,那么有:
f[i][j]=sum{f[i-1][j-k*i]},0<=k<=i
我们在DP的时候,假设当前要计算f[i][j],可以设tmp[v]为当前满足t mod i=v的f[i-1][t]的和
然后就可以通过维护tmp数组,轻松计算出f[i][j]了
这一步的时间复杂度是O(nsqrt(n))
 
接下来考虑大小大于S的物品

我们考虑一个给物品“动态添加大小”的DP:
令g[i][j]表示,当前有i个物品,大小总和为j
我们可以做的转移是:
(1):将所有物品的大小加一 :g[i][j]->g[i][j+i]
(2):新建一个大小为S+1的物品g[i][j]->g[i+1][j+S+1]
可以发现,物品总数最多为n/S个,所有g的第一维的规模是n/S的,所以这一个DP也是O(n*sqrt(n))的
于是总复杂度就是O(n*sqrt(n))
这道题还有更加优美的算法,可以用多项式黑科技进行推导,可以得到复杂度O(nlogn)的做法,由于出题人能力有限所以这里就不阐述了
 
 #include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
#include<cmath>
#define ll long long
#define ui unsigned int
#define ull unsigned long long
const int maxn=,modd=;
int f[][maxn],g[][maxn],sm[maxn],tmp[maxn];
int i,j,k,n,m,n1; int ra;char rx;
inline int read(){
rx=getchar(),ra=;
while(rx<''||rx>'')rx=getchar();
while(rx>=''&&rx<='')ra*=,ra+=rx-,rx=getchar();return ra;
} #define MOD(x) x-=x>=modd?modd:0
#define UPD(x) x+=x<0?modd:0
int main(){
n=read(),n1=sqrt(n);register int i,j,k; bool now=,pre=;f[][]=;int mod;
for(i=;i<=n1;i++,std::swap(now,pre)){
memset(tmp,,i<<),mod=-;
for(j=,k=-i*i;j<=n;j++,k++){
if(++mod>=i)mod=;
tmp[mod]+=f[pre][j],MOD(tmp[mod]),
f[now][j]=tmp[mod];
if(k>=)tmp[mod]-=f[pre][k],UPD(tmp[mod]);
}
}//printf("n1:%d\n",n1);
//for(i=1;i<=n;i++)printf(" %d",f[pre][i]);puts("");
int n2=n/n1;
bool now1=,pre1=;g[][]=;
for(i=;i<=n2;i++,std::swap(now1,pre1)){
memset(g[now1],,(n1+)<<);
for(j=n1+,k=;j<=n;j++,k++)g[now1][j]=g[pre1][k];
for(j=i;j<=n;j++)g[now1][j]+=g[now1][j-i],MOD(g[now1][j]);
for(j=;j<=n;j++)sm[j]+=g[now1][j],MOD(sm[j]);
}
int ans=f[pre][n]+sm[n];MOD(ans);
for(i=;i<n;i++)ans=(ans+1ll*f[pre][i]*sm[n-i])%modd;
printf("%d\n",ans);
}

[51nod1597]有限背包计数问题的更多相关文章

  1. 2018.09.25 51nod1597 有限背包计数问题(背包+前缀和优化)

    传送门 dp好题. 我认为原题的描述已经很清楚了: 你有一个大小为n的背包,你有n种物品,第i种物品的大小为i,且有i个,求装满这个背包的方案数有多少. 两种方案不同当且仅当存在至少一个数i满足第i种 ...

  2. 51Nod 有限背包计数问题 题解报告

    首先这道题理论上是可以做到O(nlogn)的,因为OEIS上有一个明显可以用多项式乘法加速的式子 但是由于模数不是很兹磁,所以导致nlogn很难写 在这里说一下O(n*sqrt(n))的做法 首先我们 ...

  3. 51Nod1957 有限背包计数问题

    传送门 另一个传送门 这题还挺有意思…… 先贴一波出题人的题解…… (啥你说你看不见?看来你还没过啊,等着A了再看或者乖乖花点头盾好了……) 然后是我的做法……思想都是一样的,只是细节不一样而已…… ...

  4. 51nod 1597 有限背包计数问题 (背包 分块)

    题意 题目链接 Sol 不会做啊AAA.. 暴力上肯定是不行的,考虑根号分组 设\(m = \sqrt{n}\) 对于前\(m\)个直接暴力,利用单调队列优化多重背包的思想,按\(\% i\)分组一下 ...

  5. 题解 51nod 1597 有限背包计数问题

    题目传送门 题目大意 给出 \(n\),第 \(i\) 个数有 \(i\) 个,问凑出 \(n\) 的方案数. \(n\le 10^5\) 思路 呜呜呜,傻掉了... 首先想到根号分治,分别考虑 \( ...

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

    LOJ #6089. 小 Y 的背包计数问题 神仙题啊orz. 首先把数分成\(<=\sqrt n\)的和\(>\sqrt n\)的两部分. \(>\sqrt n\)的部分因为最多选 ...

  7. 【LOJ6089】小Y的背包计数问题(动态规划)

    [LOJ6089]小Y的背包计数问题(动态规划) 题面 LOJ 题解 神仙题啊. 我们分开考虑不同的物品,按照编号与\(\sqrt n\)的关系分类. 第一类:\(i\le \sqrt n\) 即需要 ...

  8. LOJ6089 小Y的背包计数问题(根号优化背包)

    Solutioon 这道题利用根号分治可以把复杂度降到n根号n级别. 我们发现当物品体积大与根号n时,就是一个完全背包,换句话说就是没有了个数限制. 进一步我们发现,这个背包最多只能放根号n个物品. ...

  9. LOJ6089 小Y的背包计数问题 背包、根号分治

    题目传送门 题意:给出$N$表示背包容量,且会给出$N$种物品,第$i$个物品大小为$i$,数量也为$i$,求装满这个背包的方案数,对$23333333$取模.$N \leq 10^5$ $23333 ...

随机推荐

  1. 后台返回数据事null时怎么进行判断

    p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px "Helvetica Neue"; color: #454545 } p. ...

  2. APP Store开发指南

    App Store 审核指南 iOS App打包上架超详细流程 ---2017.03 苹果对开发者提交的应用的审核之严格是出了名的,了解苹果的审核标准对于开发者防止应用被拒有着十分重要的意义.几天前苹 ...

  3. npm的使用总结

    npm常用命令 npm list 查看当前目录下已安装的包 npm root -g 查看全局安装的包的路径 npm help 查看全部命令 npm update/uninstall moduleNam ...

  4. Ant学习笔记

    前言:这段时间在学习Ant,发现这是一个很强大的构建工具.你可能使用了很长一段时间,才发现Ant能做数不完的事.总之,个人觉得,Ant学习门槛低,入门简单,能大概看懂程序,写一些简单的脚本即可,剩下在 ...

  5. bzoj 2750: [HAOI2012]Road

    Description C国有n座城市,城市之间通过m条单向道路连接.一条路径被称为最短路,当且仅当不存在从它的起点到终点的另外一条路径总长度比它小.两条最短路不同,当且仅当它们包含的道路序列不同.我 ...

  6. 阅读MDN文档之层叠与继承(二)

    目录 The cascade Importance Specificity Source order A note on rule mixing Inheritance Controlling inh ...

  7. 【Tomcat】重新打war包

    Extract war in tomcat/webapps #!/bin/bash #----------------------------------------------- # FileNam ...

  8. UNIX域协议(命名套接字)

    这里主要介绍命名UNIX域套接字 1.什么是UNIX域套接字Unix域协议并不是一个实际的协议族,而是在单个主机上执行客户/服务通信的一种方式.是进程间通信(IPC)的一种方式.它提供了两类套接字:字 ...

  9. Django2中文文档--目录及介绍部分

    Django2文档-文档结构 我是按照官方文档的格式进行翻译,所以格式根官方格式一致 如果大家发现哪些地方有问题可以联系我 2426525089@qq.com 或者加入QQ群跟我一起翻译,群号码: 2 ...

  10. Extjs 取消backspace事件

    Ext.getDoc().on('keydown',function(e){ if(e.getKey() == 8 && e.getTarget().type =='text' &am ...