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 & ... 
随机推荐
- Spring  SimpleJdbcOperations 批量更新
			1.控制台代码 import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.RowM ... 
- sql语句-4-子查询
- 【LG5020】[NOIP2018]货币系统
			[LG5020][NOIP2018]货币系统 题面 洛谷 题解 考场上第一眼还不会233 可以发现只要可以被其他的货币通过一些奇奇怪怪的方式表示出来的货币就\(ban\)掉即可 就是个完全背包 我是统 ... 
- python全栈开发-前方高能-生成器和生成器表达式
			python_day_13 今日主要内容1. 生成器和生成器函数生成器的本质就是迭代器生成器的三种创建办法: 1.通过生成器函数 2.通过生成器表达式创建生成器 3.通过数据转换 生成器函数: 函数中 ... 
- ffmpeg 踩坑实录 近期使用总结(三)
			一.背景介绍 将ffmpeg运用到项目上已经有一段时间了,趁现在有空赶紧记下来. 二.技术点总结 2.1 实现方式 项目里面主要运用的形式是,在java端,调用操作系统的方法,并执行切片命令. ... 
- JAVA学习笔记--初识容器类库
			一.前言 JAVA中一切皆为对象,因而,持有对象显得尤为重要. 在JAVA中,我们可以通过创建一个对象的引用的方式来持有对象: HoldingObject holding; 也可以创建一个对象数组来持 ... 
- Valgrind 简单用法
			有时需要给自己写的小程序做个简单的 benchmark,查看内存使用情况和运行时间.这时可以试试 valgrind. Ubuntu 下安装很简单: sudo apt-get update sudo a ... 
- Python中的构造函数
			Python中的构造函数是__init__函数.在Python中,子类如果定义了构造函数,而没有调用父类的,那么Python不会自动调用,也就是说父类的构造函数不会执行. 比如有test.py的mod ... 
- USACO 1.4.2 Mother's Mil 母亲的牛奶(DFS)
			Description 农民约翰有三个容量分别是A,B,C升的桶,A,B,C分别是三个从1到20的整数,最初,A和B桶都是空的,而C桶是装满牛奶的.有时,约翰把牛奶从一个桶倒到另一个桶中,直到被灌桶装 ... 
- Thunder团队第七周 - Scrum会议3
			Scrum会议3 小组名称:Thunder 项目名称:i阅app Scrum Master:李传康 工作照片: 参会成员: 王航:http://www.cnblogs.com/wangh013/ 李传 ... 
