51Nod1957 有限背包计数问题
这题还挺有意思……
先贴一波出题人的题解……
(啥你说你看不见?看来你还没过啊,等着A了再看或者乖乖花点头盾好了……)
然后是我的做法……思想都是一样的,只是细节不一样而已……
令$B=\lceil \sqrt{n}\rceil$,把物品分$\ge B$和$<B$两类考虑:
对于大小$<B$的物品,直接用多重背包计数的方法去做即可,令$f[i][j]$表示使用前$i$个物品凑出$j$的方案数,显然有
\begin{align}f[i][j]=\sum_{k=0}^i f[i-1][j-ki]\end{align}
直接算的话时间肯定会爆炸,所以简单变形一下,得到
$f[i][j]=f[i][j-i]+f[i-1][j]-f[i-1][i(i+1)]$
应该不难理解,就是对上一个状态的转移区间做一下微调,加上右端点并减掉左端点。
这样每个状态的计算时间就变成$O(1)$了,而总共有$O(n\sqrt{n})$个状态,因此这部分的复杂度就是$O(n\sqrt{n})$。
对于大小$\ge B$的物品,显然这些物品是用不完的,直接当作完全背包处理即可。又因为这些物品最多使用$\lfloor \frac n B\rfloor$个,因此可以令$g[i][j]$表示强制只能使用大小$\ge B$的物品时用$i$个物品凑出$j$的方案数。
直接算不太好算,我们考虑给物品动态添加大小:
$g[i][j]=g[i-1][j-B]+g[i][j-i]$
前一种是添加一个大小为$B$的物品,后一种是把所有物品的大小都$+1$,应该不难看出来这样可以做到不重不漏地统计所有方案。
使用的物品数不会超过$\sqrt{n}$,因此状态数仍然是$O(n\sqrt{n})$,单次转移$O(1)$,这样后半部分的复杂度就也是$O(n\sqrt{n})$了。
最后合并两部分的结果即可,显然有
\begin{align}Ans=\sum_{i=0}^n f[n-i]\sum_{j=0}^{\lfloor\frac n B\rfloor}g[j][n-i]\end{align}
直接算是$O(n\sqrt{n})$的,如果在算$g$的时候顺便算一下$h[j]=\sum_i g[i][j]$的话可以降到$O(n)$,再加上分块DP的复杂度,总复杂度就是$O(n\sqrt{n})$。
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const int maxn=,p=;
int n,B,f[][maxn]={{}},g[][maxn]={{}},h[maxn]={},cur=,ans=;
int main(){
scanf("%d",&n);
B=(int)ceil(sqrt(n));
f[][]=g[][]=h[]=;
for(int i=;i*B<=n;i++){
cur^=;
for(int j=(i-)*B;j<i*B;j++)g[cur][j]=;
for(int j=i*B;j<=n;j++){
g[cur][j]=g[cur^][j-B];
if(j>=i)g[cur][j]=(g[cur][j]+g[cur][j-i])%p;
h[j]=(h[j]+g[cur][j])%p;
}
}
cur=;
for(int i=;i<B;i++){
cur^=;
for(int j=;j<=n;j++){
f[cur][j]=f[cur^][j];
if(j>=i){
f[cur][j]=(f[cur][j]+f[cur][j-i])%p;
if(j>=i*(i+))f[cur][j]=(f[cur][j]-f[cur^][j-i*(i+)])%p;
}
}
}
for(int i=;i<=n;i++)ans=(ans+(int)((long long)f[cur][i]*h[n-i]%p))%p;
if(ans<)ans+=p;
printf("%d",ans);
return ;
}
话说听说这题有多项式乘法加速的$O(n\log n)$做法,然而翻了翻51Nod的排行榜并没有看到写这种做法的……看了半天OEIS也没看懂怎么用多项式乘法加速,算了反正分块跑得也挺快我就用分块算了……
51Nod1957 有限背包计数问题的更多相关文章
- [51nod1597]有限背包计数问题
你有一个大小为n的背包,你有n种物品,第i种物品的大小为i,且有i个,求装满这个背包的方案数有多少 两种方案不同当且仅当存在至少一个数i满足第i种物品使用的数量不同 Input 第一行一个正整数n 1 ...
- 51Nod 有限背包计数问题 题解报告
首先这道题理论上是可以做到O(nlogn)的,因为OEIS上有一个明显可以用多项式乘法加速的式子 但是由于模数不是很兹磁,所以导致nlogn很难写 在这里说一下O(n*sqrt(n))的做法 首先我们 ...
- 2018.09.25 51nod1597 有限背包计数问题(背包+前缀和优化)
传送门 dp好题. 我认为原题的描述已经很清楚了: 你有一个大小为n的背包,你有n种物品,第i种物品的大小为i,且有i个,求装满这个背包的方案数有多少. 两种方案不同当且仅当存在至少一个数i满足第i种 ...
- 51nod 1597 有限背包计数问题 (背包 分块)
题意 题目链接 Sol 不会做啊AAA.. 暴力上肯定是不行的,考虑根号分组 设\(m = \sqrt{n}\) 对于前\(m\)个直接暴力,利用单调队列优化多重背包的思想,按\(\% i\)分组一下 ...
- 题解 51nod 1597 有限背包计数问题
题目传送门 题目大意 给出 \(n\),第 \(i\) 个数有 \(i\) 个,问凑出 \(n\) 的方案数. \(n\le 10^5\) 思路 呜呜呜,傻掉了... 首先想到根号分治,分别考虑 \( ...
- LOJ #6089. 小 Y 的背包计数问题
LOJ #6089. 小 Y 的背包计数问题 神仙题啊orz. 首先把数分成\(<=\sqrt n\)的和\(>\sqrt n\)的两部分. \(>\sqrt n\)的部分因为最多选 ...
- 【LOJ6089】小Y的背包计数问题(动态规划)
[LOJ6089]小Y的背包计数问题(动态规划) 题面 LOJ 题解 神仙题啊. 我们分开考虑不同的物品,按照编号与\(\sqrt n\)的关系分类. 第一类:\(i\le \sqrt n\) 即需要 ...
- LOJ6089 小Y的背包计数问题(根号优化背包)
Solutioon 这道题利用根号分治可以把复杂度降到n根号n级别. 我们发现当物品体积大与根号n时,就是一个完全背包,换句话说就是没有了个数限制. 进一步我们发现,这个背包最多只能放根号n个物品. ...
- LOJ6089 小Y的背包计数问题 背包、根号分治
题目传送门 题意:给出$N$表示背包容量,且会给出$N$种物品,第$i$个物品大小为$i$,数量也为$i$,求装满这个背包的方案数,对$23333333$取模.$N \leq 10^5$ $23333 ...
随机推荐
- POJ1330 Nearest Common Ancestors (JAVA)
经典LCA操作.. 贴AC代码 import java.lang.reflect.Array; import java.util.*; public class POJ1330 { // 并查集部分 ...
- javax.jms.JMSException: Could not connect to broker URL: tcp://localhost:61616. Reason: java.net.ConnectException: Connection timed out: connect
本地测试向服务器中ActiveMQ添加队列数据,报错连接超时 解决: 查看服务器端口号是否存在,(最好是0.0.0.0格式的,虽然暂时还不知道为啥得这个格式) 通过telnet测试该端口不通(6161 ...
- JavaWeb后台从input表单获取文本值的两种方式
JavaWeb后台从input表单获取文本值的两种方式 #### index.html <!DOCTYPE html> <html lang="en"> & ...
- odoo 的一些orm 操作
1.基础文件及目录结构 在认识odoo ORM框架前,先介绍一下odoo中模块目录结构. data:存放模块预制数据 i18n:存放国际化文件 models:存放模型等py代码 securit ...
- ifconfig无输出的原因及解决办法
问题 执行 ifconfig 命令无任何报错,也无任何输出信息 [root@linuxprobe ~]# ifconfig[root@linuxprobe ~]# 排错 1. 检查PATH变量 [r ...
- ptyhon技能树及其学习资源
GUI编程 tkinter Github项目 Tkinter by example effbot 文档 tkinter的一个designer,可以像在qtdesign那样创建UI文件 pyqt5 py ...
- js获取字符串字节的位数
ifSubUser.getBlength = function(str){ ;i--;){ n += str.charCodeAt(i) > ? : ; } return n; }
- html5在手机熄屏后倒计时会出现延迟情况
今天开发了一个手机端的倒计时,然后同事说出现了Bug,怎么回事呢?Bug很简单,就是在手机返回主界面或者熄屏后倒计时会暂停在熄屏前的时间(注意时间是页面加载时获取的服务器的时间),问题很简单,知道问题 ...
- mysql 必知必会总结
以前 mysql 用的不是很多, 2 天看了一遍 mysql 必知必会又复习了一下基础. 200 页的书,很快就能看完, 大部分知识比较基础, 但还是了解了一些以前不知道的知识点.自己做一个备份,随 ...
- android LinearLayoutForListView
由于 scrollview 套 listview 会有很多问题,网上很多人用 LinearLayout 模拟 listview, 也可以设置 adapter. 很多人直接继承 BaseAdapter, ...