BZOJ3591: 最长上升子序列
因为是一个排列,所以可以用$n$位二进制数来表示$O(n\log n)$求LIS时的单调栈。
首先通过$O(n^22^n)$的预处理,求出每种LIS状态后面新加一个数之后的状态。
设$f[i][j]$表示已选数字集合为$i$,LIS状态为$j$的方案数。
转移时枚举不在$i$里的数$t$,如果$t$在给定的LIS中,那么它加入时需要检验它的前一个是否已经被加入。
对于状态的存储,可以考虑三进制,0表示没选,1表示选了但是不在栈中,2表示在栈里。那么只要将两个二进制数看作三进制,然后相加即可。
时间复杂度$O(n3^n)$。
#include<cstdio>
#define N 15
int n,m,i,j,k,p[N],g[N][1<<N],pow[N],a[1<<N],f[14348907],ans;
int main(){
scanf("%d%d",&n,&m);
for(i=0;i<n;i++)p[i]=-1;
for(i=0;i<m;i++)scanf("%d",&j),p[j-1]=k-1,k=j;
for(pow[0]=i=1;i<n;i++)pow[i]=pow[i-1]*3;
for(i=0;i<1<<n;i++)for(j=0;j<n;j++)if(!(i>>j&1)){
g[j][i]=i|(1<<j);
for(k=j+1;k<n;k++)if(i>>k&1)break;
if(k<n)g[j][i]^=1<<k;
}else a[i]+=pow[j];
for(i=0;i<n;i++)if(p[i]<0)f[pow[i]<<1]=1;
for(i=1;i<1<<n;i++)for(k=0;k<n;k++)if(!(i>>k&1)){
if(~p[k])if(!(i>>p[k]&1))continue;
for(j=i;j;j=(j-1)&i)if(f[a[i]+a[j]])f[a[i|(1<<k)]+a[g[k][j]]]+=f[a[i]+a[j]];
}
for(i=1;i<1<<n;i++)if(__builtin_popcount(i)==m)ans+=f[a[(1<<n)-1]+a[i]];
return printf("%d",ans),0;
}
BZOJ3591: 最长上升子序列的更多相关文章
- 【dp 状态压缩 单调栈】bzoj3591: 最长上升子序列
奇妙的单调栈状压dp Description 给出1~n的一个排列的一个最长上升子序列,求原排列可能的种类数. Input 第一行一个整数n. 第二行一个整数k,表示最长上升子序列的长度. 第三行k个 ...
- BZOJ3591 最长上升子序列(状压dp)
之前听说过一种dp套dp的trick,大致是用另一个dp过程中用到的一些东西作为该dp的状态.这个题比较类似. 考虑求LIS时用到的单调队列.设f[S]为所选取集合为S的方案数,其中在单调队列内的标2 ...
- 用python实现最长公共子序列算法(找到所有最长公共子串)
软件安全的一个小实验,正好复习一下LCS的写法. 实现LCS的算法和算法导论上的方式基本一致,都是先建好两个表,一个存储在(i,j)处当前最长公共子序列长度,另一个存储在(i,j)处的回溯方向. 相对 ...
- 动态规划之最长公共子序列(LCS)
转自:http://segmentfault.com/blog/exploring/ LCS 问题描述 定义: 一个数列 S,如果分别是两个或多个已知数列的子序列,且是所有符合此条件序列中最长的,则 ...
- [Data Structure] LCSs——最长公共子序列和最长公共子串
1. 什么是 LCSs? 什么是 LCSs? 好多博友看到这几个字母可能比较困惑,因为这是我自己对两个常见问题的统称,它们分别为最长公共子序列问题(Longest-Common-Subsequence ...
- 动态规划求最长公共子序列(Longest Common Subsequence, LCS)
1. 问题描述 子串应该比较好理解,至于什么是子序列,这里给出一个例子:有两个母串 cnblogs belong 比如序列bo, bg, lg在母串cnblogs与belong中都出现过并且出现顺序与 ...
- LintCode 77: 最长公共子序列
public class Solution { /** * @param A, B: Two string. * @return: the length of the longest common s ...
- 最长下降子序列O(n^2)及O(n*log(n))解法
求最长下降子序列和LIS基本思路是完全一样的,都是很经典的DP题目. 问题大都类似于 有一个序列 a1,a2,a3...ak..an,求其最长下降子序列(或者求其最长不下降子序列)的长度. 以最长下降 ...
- 删除部分字符使其变成回文串问题——最长公共子序列(LCS)问题
先要搞明白:最长公共子串和最长公共子序列的区别. 最长公共子串(Longest Common Substirng):连续 最长公共子序列(Longest Common Subsequence,L ...
随机推荐
- 《Thinking in Java》十四章类型信息_习题解
1~10 Page 318 练习1. 在ToyTest.java中,将Toy的默认构造器注释掉,并解释发生的现象. 书中代码如下(略有改动): package org.cc.foo_008; p ...
- OkHttp学习总结
This paper mainly includes the following contents okhttp ordinary operation. okhttp interceptors. Re ...
- Android Programming: Pushing the Limits -- Chapter 7:Android IPC -- ApiWrapper
前面两片文章讲解了通过AIDL和Messenger两种方式实现Android IPC.而本文所讲的并不是第三种IPC方式,而是对前面两种方式进行封装,这样我们就不用直接把Aidl文件,java文件拷贝 ...
- 一般处理程序获取session值
1.要在一般处理程序中获取其他页面的session值,需要引用名空间: using System.Web.SessionState; 2.然后继承一个接口:IRequiresSessionState, ...
- ASP.NET MVC 伪静态的实现
public class RouteConfig { public static void RegisterRoutes(RouteCollection routes) { routes.Ignore ...
- 重温WCF之发送和接收SOAP头(三)
SOAP头可以理解为一种附加信息,就是附加到消息正文的内容. 既然消息头是附加信息,那有啥用呢?你可别说,有时候还真有不少用处.举个例子,WCF的身份验证是不是很麻烦?还要颁发什么证书的(当然不是荣誉 ...
- ODATA WEB API(一)---扩展使用
一.概述 时间也算充足,抽点时间总结下OData的常用的使用方式,开放数据协议(OData)是一个查询和更新数据的Web协议.OData应用了web技术如HTTP.Atom发布协议(AtomPub)和 ...
- RAC NTP/CTSS
本文總結主要參考: http://blog.itpub.net/23135684/viewspace-759693/ http://www.happyworld.net.cn/post/6.html ...
- .NET Expression Tree
Expression Tree 第一个简单的例子. [TestMethod] public void GodTest() { Expression<Func<int, int, int&g ...
- C# Thread 线程状态知识
.NET 基础类库的System.Threading命名空间提供了大量的类和接口支持多线程.这个命名空间有很多的类.System.Threading.Thread类是创建并控制线程,设置其优先级并获取 ...