BZOJ3591 最长上升子序列(状压dp)
之前听说过一种dp套dp的trick,大致是用另一个dp过程中用到的一些东西作为该dp的状态。这个题比较类似。
考虑求LIS时用到的单调队列。设f[S]为所选取集合为S的方案数,其中在单调队列内的标2不在的标1。转移时考虑选择一个数是否合法,这只需要保证LIS长度不超过k且所给数的相对顺序不变。
注意dp顺序,从小到大先枚举选了哪些数再枚举哪些在单调队列里。以及注意卡常。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
int read()
{
int x=,f=;char c=getchar();
while (c<''||c>'') {if (c=='-') f=-;c=getchar();}
while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
return x*f;
}
#define N 15
int n,m,id[N],p[N+],f[];
bool flag[<<N][N];
int v[<<N][N],c[<<N],mx[<<N],s[<<N],ans=;
int main()
{
#ifndef ONLINE_JUDGE
freopen("bzoj3591.in","r",stdin);
freopen("bzoj3591.out","w",stdout);
const char LL[]="%I64d\n";
#else
const char LL[]="%lld\n";
#endif
n=read(),m=read();
for (int i=;i<=m;i++) id[read()-]=i;
p[]=;for (int i=;i<=n;i++) p[i]=p[i-]*;
for (int i=;i<(<<n);i++)
for (int j=;j<n;j++)
if (!(i&(<<j)))
{
if (!id[j]) flag[i][j]=;
else
{
int tot=;
for (int k=;k<n;k++)
if ((i&(<<k))) tot+=(id[k]>);
if (tot+==id[j]) flag[i][j]=;
}
int t=-,x=;
for (int k=;k<n;k++)
if (i&(<<k)) x+=p[k];
for (int k=n-;k>j;k--)
if (i&(<<k)) t=k;
if (~t) v[i][j]=x-p[t]+p[j];
else v[i][j]=x+p[j];
}
else c[i]+=p[j],mx[i]=max(mx[i],j),s[i]++;
f[]=;
for (int x=;x<(<<n);x++)
for (int y=x;y>||y==&&x==;x==?y--:y=y-&x)
if (f[c[x]+c[y]])
{
int i=c[x]+c[y],z=c[x];
for (int j=;s[y]==m?j<mx[y]:j<n;j++)
if (flag[x][j]) f[z+p[j]+v[y][j]]+=f[i];
if (x==(<<n)-) ans+=f[i];
}
cout<<ans;
return ;
}
BZOJ3591 最长上升子序列(状压dp)的更多相关文章
- 【bzoj5161】最长上升子序列 状压dp+打表
题目描述 现在有一个长度为n的随机排列,求它的最长上升子序列长度的期望. 为了避免精度误差,你只需要输出答案模998244353的余数. 输入 输入只包含一个正整数n.N<=28 输出 输出只包 ...
- BZOJ.3591.最长上升子序列(状压DP)
BZOJ 题意:给出\(1\sim n\)的一个排列的一个最长上升子序列,求原排列可能的种类数. \(n\leq 15\). \(n\)很小,参照HDU 4352这道题,我们直接把求\(LIS\)时的 ...
- bzoj5161 最长上升子序列 状压DP(DP 套 DP) + 打表
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=5161 题解 回顾一下以前用二分求 LIS 的方法:令 \(f[i]\) 表示长度为 \(i\) ...
- BZOJ 5161: 最长上升子序列 状压dp+查分
好神啊 ~ 打表程序: #include <cstdio> #include <cstring> #include <algorithm> #define N 14 ...
- 洛谷 P4484 - [BJWC2018]最长上升子序列(状压 dp+打表)
洛谷题面传送门 首先看到 LIS 我们可以想到它的 \(\infty\) 种求法(bushi),但是对于此题而言,既然题目出这样一个数据范围,硬要暴搜过去也不太现实,因此我们需想到用某种奇奇怪怪的方式 ...
- 【dp 状态压缩 单调栈】bzoj3591: 最长上升子序列
奇妙的单调栈状压dp Description 给出1~n的一个排列的一个最长上升子序列,求原排列可能的种类数. Input 第一行一个整数n. 第二行一个整数k,表示最长上升子序列的长度. 第三行k个 ...
- hdu 4352 "XHXJ's LIS"(数位DP+状压DP+LIS)
传送门 参考博文: [1]:http://www.voidcn.com/article/p-ehojgauy-ot.html 题解: 将数字num字符串化: 求[L,R]区间最长上升子序列长度为 K ...
- hdu4352-XHXJ's LIS状压DP+数位DP
(有任何问题欢迎留言或私聊 && 欢迎交流讨论哦 题意:传送门 原题目描述在最下面. 在区间内把整数看成一个阿拉伯数字的集合,此集合中最长严格上升子序列的长度为k的个数. 思路: ...
- 「算法笔记」状压 DP
一.关于状压 dp 为了规避不确定性,我们将需要枚举的东西放入状态.当不确定性太多的时候,我们就需要将它们压进较少的维数内. 常见的状态: 天生二进制(开关.选与不选.是否出现--) 爆搜出状态,给它 ...
- fzu2188 状压dp
G - Simple String Problem Time Limit:2000MS Memory Limit:32768KB 64bit IO Format:%I64d & ...
随机推荐
- hadoop hdfs 找不到本地库解决办法
export LD_LIBRARY_PATH=/usr/lib/hadoop-0.20-mapreduce/lib/native/Linux-amd64-64 <-- HAOOP_HOME/li ...
- spring源码-aop-5
一.在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术.AOP是OOP的延续,是软件开发 ...
- Swoole实现h5版聊天室笔记
声明:该聊天室目前只有一对多,一对一的聊天功能,另外,因为没有使用到mysql,所以还存在比较多的缺陷地方,但知道原理就差不多了,这里主要分享下swoole简易的聊天室制作思路. 开发环境:cento ...
- Vue学习计划基础笔记(四) - 事件处理
事件处理 目标: 熟练掌握事件监听的方式,熟悉事件处理方式以及各类事件修饰符 理解在html中监听事件的意义 监听事件(v-on) 类似普通的on,例如v-on:click或@click就相当于普通的 ...
- 三点须知:当我们在开发过程中需要用到分布式缓存Redis的时候
当我们在开发过程中需要用到分布式缓存Redis的时候,我们首先要明白缓存在系统中用来做什么? 1. 少量数据存储,高速读写访问.通过数据全部in-momery 的方式来保证高速访问,同时提供数据落地的 ...
- spring-boot-mybatis搭建
写在开始 mybatis是一个持久化框架,支持手动sql.存储过程.高级映射.mybatis支持XML方式或注解方式将POJO与数据库表间建立映射. maven依赖 spring-boot.mysql ...
- Python3基础-表达式和运算符
表达式和运算符 什么是表达式? 1+2*3就是一个表达式,这里的加号和乘号叫做运算符,1.2.3叫做操作数. 1+2*3经过计算后得到的结果是7,我们可以将计算结果存放在一个变量里,result=1+ ...
- sprint1_11.15燃尽图(第二天)
找相关的图片资料用于做点餐系统的界面 燃尽图:
- 20181120-10 Beta阶段第2周/共2周 Scrum立会报告+燃尽图 7
此作业要求参见:[https://edu.cnblogs.com/campus/nenu/2018fall/homework/2415] 版本控制地址 [https://git.coding.n ...
- GIT团队实战
项目要求 组长博客 遇到的困难及解决办法 组员1(组长):王彬 遇到的困难 在团队任务分工的时候没有充分照顾到所有人,导致队员们的工作量不均. 现场编程时间不够 解决办法 在此对组员们表示抱歉,由于 ...