最长上升序列2 — LIS2

Description

已知一个 1 ∼ N 的排列的最长上升子序列长度为 K ,求合法的排列个数。

Input

输入一行二个整数 N , K ( K ≤ N ≤ 15) 。

Output

输出一行一个整数,描述合法的排列个数。

Sample Input

15 8

Sample Output

37558353900

解析

这题...额...还是得打记搜.

首先,让我们回顾一下求最长上升序列的二分的方法吧(神犇可自动跳过当然神犇可能不需要看本蒟蒻的题解)

我们维护一个类似于栈的数组$q$(其实是序列但为了方便懒得打字后面就称作栈吧)

令$q[i]$表示长度为$i$的序列的最后一个元素,

那么,从$1$~$n$枚举,每次在$q$中寻找第一个大于$a[i]$(即权值)的元素,

再用$a[i]$去更新它,并且它的下标就是以$a[i]$结尾的最长上升序列.

最后,再从$1$~$n$扫一遍,取最大值就行了.

那么,回到这题,

我们在搜索时,保留三个信息$s$,\(t\),\(len\),

$s$表示栈中的信息,$t$表示每个数字是否被选中,$len$表示最长上升子序列,

并且,\(s\),$t$都可以状压,

对于$s$,用一个三进制数表示,0表示未考虑,1表示已被更新,2表示目前在栈中,

对于$t$,用二进制数表示就行了,0表示已选,1表示未选.

那么,初始状态就是(0,(1<<\(n\))-1,0),

接下来,考虑状态转移.

枚举$t$中的每个二进制位为1的数,并更新$q$(就是那个栈),

再搜索下一层,

当$t$等于0,即每个数都被选时,如果$len$等于$k$,就返回1,

如果当前的$s$已经被搜过,就直接返回就行了.

还有什么不明白的就看代码吧:

#include <cstdio>
#include <iostream>
#include <cstring>
#define ll long long
using namespace std; inline int read(){
int sum=0,f=1;char ch=getchar();
while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0' && ch<='9'){sum=sum*10+ch-'0';ch=getchar();}
return f*sum;
} int n,m;
ll f[15000001];
int a[1<<15]/*状态对应的数字*/,p[16]/*3的指数*/;
int q[10001]/*栈*/; ll dfs(int s/*栈的状态*/,int t/*数字被选的状态*/,int len/*最长上升序列的长度*/){
if(!t) return len==m;//每个数都被选了
if(f[s]!=-1) return f[s];
f[s]=0;int pos=0,tt=t;
while(t){
int k=t&-t;t^=k;//用lowbit寻找二进制位为1的状态
while(pos<len&&q[pos+1]<a[k]) pos++;
int l=q[pos+1];
q[pos+1]=a[k];//寻找并更新栈
f[s]+=dfs(s+2*p[a[k]]-p[l],tt^k,len+(pos==len));
q[pos+1]=l;//回溯
}
return f[s];
} int main(){
n=read();m=read();//m就是k,不过写习惯了[滑稽]
for(int i=1;i<=n;i++){
a[1<<(i-1)]=i;//预处理,状态所代表的数
p[i]= i==1? 1:p[i-1]*3;//三的指数
}
memset(f,0xff,sizeof(f));
printf("%lld\n",dfs(0,(1<<n)-1,0));
return 0;
}

题解 最长上升序列2 — LIS2的更多相关文章

  1. CJOJ 【DP合集】最长上升序列2 — LIS2

    题面 已知一个 1 ∼ N 的排列的最长上升子序列长度为 K ,求合法的排列个数. 好题(除了我想不出来我应该找不到缺点), 想一想最长上升子序列的二分做法, 接在序列后面或者替换. 所以对于每一个位 ...

  2. POJ 2533 Longest Ordered Subsequence 最长递增序列

      Description A numeric sequence of ai is ordered if a1 < a2 < ... < aN. Let the subsequenc ...

  3. P1091 合唱队形 DP 最长升序列维护

    题目描述 NN位同学站成一排,音乐老师要请其中的(N-KN−K)位同学出列,使得剩下的KK位同学排成合唱队形. 合唱队形是指这样的一种队形:设K位同学从左到右依次编号为1,2,…,K1,2,…,K,他 ...

  4. dp(最长升序列)

    http://poj.org/problem?id=2533   题意:给你n(1-1000)个数,求这n个数的最长升序列.   题解:dp[i]表示以第i个数结尾的最长升序列. #include & ...

  5. 521.最长特殊序列 I

    2020-05-14 最长特殊序列 I 给你两个字符串,请你从这两个字符串中找出最长的特殊序列. 「最长特殊序列」定义如下:该序列为某字符串独有的最长子序列(即不能是其他字符串的子序列). 子序列 可 ...

  6. XHXJ's LIS HDU - 4352 最长递增序列&数位dp

    代码+题解: 1 //题意: 2 //输出在区间[li,ri]中有多少个数是满足这个要求的:这个数的最长递增序列长度等于k 3 //注意是最长序列,可不是子串.子序列是不用紧挨着的 4 // 5 // ...

  7. [LeetCode] Binary Tree Longest Consecutive Sequence 二叉树最长连续序列

    Given a binary tree, find the length of the longest consecutive sequence path. The path refers to an ...

  8. [LeetCode] Longest Consecutive Sequence 求最长连续序列

    Given an unsorted array of integers, find the length of the longest consecutive elements sequence. F ...

  9. lintcode: 最长连续序列

    最长连续序列 给定一个未排序的整数数组,找出最长连续序列的长度. 说明 要求你的算法复杂度为O(n) 样例 给出数组[100, 4, 200, 1, 3, 2],这个最长的连续序列是 [1, 2, 3 ...

随机推荐

  1. 从入门到自闭之Python--MySQL数据库的操作命令

    命令: mysqld install; 配置数据库 net start mysql;启动数据库 mysql -uroot -p; 以root权限启动数据库,-p之后输入密码 mysql -uroot ...

  2. Java 封装与类

    一.面向对象编程 面向对象编程三大特性:封装.继承和多态. 类是实现封装的手段,是面向对象编程的基本单元. 封装隐藏了类的内部实现细节,暴露给外界可控的操作,提高数据的完整性和安全性,提高模块的可重用 ...

  3. oracle建表详细信息

    一张用户表 -- Create table create table OA_DM.DM_GY_USER ( ), username ) not null, loginname ) not null, ...

  4. string库

    Lua字符串库小集 1. 基础字符串函数: 字符串库中有一些函数非常简单,如: 1). string.len(s) 返回字符串s的长度: 2). string.rep(s,n) 返回字符串s重复n次的 ...

  5. 15-Perl 格式化输出

    1.Perl 格式化输出Perl 是一个非常强大的文本数据处理语言.Perl 中可以使用 format 来定义一个模板,然后使用 write 按指定模板输出数据.Perl 格式化定义语法格式如下:fo ...

  6. Sharepoint 开启App 配置App

    如果没有Enable app,打开app store的时候出出现错误: Sorry, apps are turned off. If you know who runs the server, tel ...

  7. Winfrom 定时锁屏

    #region 锁屏 public struct LASTINPUTINFO { [MarshalAs(UnmanagedType.U4)] public int cbSize; [MarshalAs ...

  8. windows下 qt5&vs2010 在qtCreator下中文乱码

    环境:windows2012下 qt5.3.1 & vs2010 在qtCreator3.1.2下中文乱码 解决方法:在相关文件中加入代码 #ifdef Q_OS_WIN32 #if _MSC ...

  9. 帝国cms 加载更多的实现(父栏目以及子栏目都可以实现)

    1. <div class="pagelist"> <span id="loadmore" class="btn" sty ...

  10. vue2中的keep-alive使用总结及注意事项

    问题总结;最近在写vue移动端的项目的时候,当我切换菜单,再切换换回去的时候,发现页面出现闪动的效果,其原因是因为切换回去之后,页面重新渲染了;为了解决这一问题:查阅资料,只需要在 入口文件 App. ...