最长上升序列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. table+ajax加载数据

    //ajax加载notice $(function() { //${pageContext.request.contextPath}/ /** var res = [ {noticeTitle:'必答 ...

  2. python新手必躺的5大坑

    python新手必躺的5大坑 对于Python新手来说,写代码很少考虑代码的效率和简洁性,因此容易造成代码冗长.执行慢,这些都是需要改进的地方.本文是想通过几个案列给新手一点启发,怎样写python代 ...

  3. PHP 协程:Go + Chan + Defer

    Swoole4为PHP语言提供了强大的CSP协程编程模式.底层提供了3个关键词,可以方便地实现各类功能. Swoole4提供的PHP协程语法借鉴自Golang,在此向GO开发组致敬 PHP+Swool ...

  4. ubuntu切换root用户

    方法一:sudo su命令 方法二:sudo -i 方法三:su root

  5. 并不对劲的复健训练-CF1205B Shortest Cycle

    题目大意 有\(n\)(\(n\leq 10^5\))个数\(a_1,...,a_n\)(\(a\leq 10^{18}\)).有一个图用这个方法生成:若\(a_i\)按位与\(a_j\)不为0,则在 ...

  6. Python(十) —— 多进程多线程

    进程线程概念 进程理解为一个程序,具体完成工作的是线程.比如说启动一个 QQ ,QQ 程序里面可以聊天,设置,查找好友等,那么这些功能就理解成各个线程,也就是单进程多线程的一个模式.进程理解成人脑子, ...

  7. c#获取桌面路径和bin文件的路径

    string path = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory): 生成的运行bin文件下的路径: ...

  8. 无障碍开发(四)之ARIA aria-***状态值

    aria-***状态值

  9. ext grid添加2行topbar

    bbar: paginToolbar(this.getStore()), dockedItems: [{ xtype: 'toolbar', dock: 'top', items: me.create ...

  10. redis的使用(Java使用Jedis客户端连接redis)

    一.添加依赖 <dependency>   <groupId>redis.clients</groupId>   <artifactId>jedis&l ...