统计$[L,R]$内LIS长度为$k$的数的个数,$Q \le 10000,L,R < 2^{63}-1,k \le 10$。


首先肯定是数位DP。然后考虑怎么做这个dp。如果把$k$记录到状态里没有用。需要找到有效方法统一的表示前面填好的数的特点方便之后的填数。

回顾LIS过程,当前数结尾的LIS是前面比他小的数的LIS中的max+1,但是没有办法记录下来,因为如果记录下前面以数字$0\sim 9$结尾的maxLIS的话空间不够。

尝试换一种表示方法。回顾LIS的$O(nlogn)$做法,发现维护了一个$g$数组表示长度$i$的LIS结尾最小$g[i]$,这个数组是单调增的。

这是发现可以方便记录——用一个数$S$,把二进制第$g[i]$位$\text{or}$到$S$上去。这样,$S$中是$1$的位置从小到大写下来就是$g$数组了。

设$f(len,S,n,lead,limit)$,$S$是之前填好的数的$g$数组,$n$是前面的最长LIS长度。枚举当前位填啥,通过二分确定新的$S$,然后边界判一下是否$n=k$就好了。


code细节:

  • 注意到$k$是相互独立的,可以分别进行统计,$f[k][...]$表示满足……条件(见上)之下、LIS长度为$k$的数的个数。
  • 注意判断前导0。
  • 加了一些剪枝,虽然并没有什么用。
 #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#define dbg(x) cerr << #x << " = " << x <<endl
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int,int> pii;
template<typename T>inline T _min(T A,T B){return A<B?A:B;}
template<typename T>inline T _max(T A,T B){return A>B?A:B;}
template<typename T>inline char MIN(T&A,T B){return A>B?(A=B,):;}
template<typename T>inline char MAX(T&A,T B){return A<B?(A=B,):;}
template<typename T>inline void _swap(T&A,T&B){A^=B^=A^=B;}
template<typename T>inline T read(T&x){
x=;int f=;char c;while(!isdigit(c=getchar()))if(c=='-')f=;
while(isdigit(c))x=x*+(c&),c=getchar();return f?x=-x:x;
}
ll f[][][<<][],b[],tot;
ll L,R;
int T,k;
ll dp(int len,int S,int n,int lead,int limit){
if(!len)return n==k;
if(n>k||n+len<k)return ;
if(!limit&&~f[k][len][S][lead])return f[k][len][S][lead];
int num=limit?b[len]:;ll ret=;
if(lead){
ret+=dp(len-,S,n,lead,limit&&!num);
for(register int i=;i<=num;++i)ret+=dp(len-,<<i,,,limit&&i==num);
}
else{
int a[]={},m=;
for(register int i=;i<=;++i)if(S&(<<i))a[++m]=i;
for(register int i=;i<=num;++i){
int pos=lower_bound(a+,a+m+,i)-a;
if(pos>m)ret+=dp(len-,S|(<<i),n+,,limit&&i==num);
else ret+=dp(len-,S^(<<a[pos])|(<<i),n,,limit&&i==num);
}
}
return limit?ret:f[k][len][S][lead]=ret;
}
inline ll solve(ll x){
tot=;while(x)b[++tot]=x%,x/=;
return dp(tot,,,,);
} int main(){//freopen("test.in","r",stdin);//freopen("test.ans","w",stdout);
read(T);memset(f,-,sizeof f);
for(register int i=;i<=T;++i)
read(L),read(R),read(k),printf("Case #%d: %lld\n",i,solve(R)-solve(L-));
return ;
}

总结:还是那句话,用有效的方法表示好填好的数的性质。

hdu4352 XHXJ's LIS[数位DP套状压DP+LIS$O(nlogn)$]的更多相关文章

  1. 树形DP和状压DP和背包DP

    树形DP和状压DP和背包DP 树形\(DP\)和状压\(DP\)虽然在\(NOIp\)中考的不多,但是仍然是一个比较常用的算法,因此学好这两个\(DP\)也是很重要的.而背包\(DP\)虽然以前考的次 ...

  2. dp乱写1:状态压缩dp(状压dp)炮兵阵地

    https://www.luogu.org/problem/show?pid=2704 题意: 炮兵在地图上的摆放位子只能在平地('P') 炮兵可以攻击上下左右各两格的格子: 而高原('H')上炮兵能 ...

  3. poj2411 Mondriaan's Dream (轮廓线dp、状压dp)

    Mondriaan's Dream Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 17203   Accepted: 991 ...

  4. dp,状压dp等 一些总结

    也就作业几题而已,分析一下提醒 最重要的就是,记住,没用的状态无论怎么转移最后都会是没用的状态,所以每次转移以后的有值的状态都是有用的状态. 几种思考方向: 第一种:枚举当前的状态,转移成另外一个状态 ...

  5. BZOJ 4042 Luogu P4757 [CERC2014]Parades (树形DP、状压DP)

    题目链接 (BZOJ) https://www.lydsy.com/JudgeOnline/problem.php?id=4042 (Luogu) https://www.luogu.org/prob ...

  6. hdu4352 XHXJ's LIS (数位dp)

    Problem Description #define xhxj (Xin Hang senior sister(学姐))  If you do not know xhxj, then careful ...

  7. hoj 2662 经典状压dp // MyFirst 状压dp

    题目链接:http://acm.hit.edu.cn/hoj/problem/view?id=2662 1.引言:用dp解决一个问题的时候很重要的一环就是状态的表示,一般来说,一个数组即可保存状态. ...

  8. hdu4352 XHXJ's LIS(数位DP + LIS + 状态压缩)

    #define xhxj (Xin Hang senior sister(学姐)) If you do not know xhxj, then carefully reading the entire ...

  9. 【BZOJ3925】地震后的幻想乡(期望概率DP,状压DP)

    题意:给定一张点数不超过10的无向连通图,每条边有一个[0,1]之间的随机权值,求最小生成树上最大边的期望值 提示:对于n个[0,1]之间的随机变量x1,x2,...,xn,第k小的那个的期望值是k/ ...

随机推荐

  1. SQL常见面试题(学生表_课程表_总表)

    问题描述: 为管理岗位业务培训信息,建立3个表: S (S#,SN,SD,SA) S#,SN,SD,SA 分别代表学号.学员姓名.所属单位.学员年龄 C (C#,CN ) C#,CN 分别代表课程编号 ...

  2. Smarty快速入门

    1.Smarty是用纯php语言写的类 2.功能是实现前后端分离 3.Smarty简洁高效 4.快速入门案例 1.下载 smarty源码 https://www.smarty.net/ 2.搭建PHP ...

  3. Java中String连接性能的分析

    总结:如果String的数量小于4(不含4),使用String.concat()来连接String,否则首先计算最终结果的长度,再用该长度来创建一个StringBuilder,最后使用这个String ...

  4. 2019.11.9 csp-s 考前模拟

    2019.11.9 csp-s 考前模拟 是自闭少女lz /lb(泪奔 T1 我可能(呸,一定是唯一一个把这个题写炸了的人 题外话: 我可能是一个面向数据编程选手 作为一个唯一一个写炸T1的人,成功通 ...

  5. 【pytorch】学习笔记(一)-张量

    pytorch入门 什么是pytorch PyTorch 是一个基于 Python 的科学计算包,主要定位两类人群: NumPy 的替代品,可以利用 GPU 的性能进行计算. 深度学习研究平台拥有足够 ...

  6. [BZOJ1576] [BZOJ3694] [USACO2009Jan] 安全路径(最短路径+树链剖分)

    [BZOJ1576] [BZOJ3694] [USACO2009Jan] 安全路径(最短路径+树链剖分) 题面 BZOJ1576和BZOJ3694几乎一模一样,只是BZOJ3694直接给出了最短路树 ...

  7. 从入门到自闭之python三大器--装饰器进阶

    装饰器的进阶 有参装饰器: # def warpper(func): # def inner(*args,**kwargs): # user = input("user:") # ...

  8. python-day30(正式学习)

    单例模式 什么是单例模式 单例模式:基于某种方法实例化多次得到实例是同一个 为什么用单例模式 当实例化多次得到的对象中存放的属性都一样的情况,应该将多个对象指向同一个内存,即同一个实例 用类方法来实现 ...

  9. EJB通过注解方式注入并使用其它EJB或者服务、配置JBoss数据源

    版权声明:本文为博主原创文章,转载请注明出处. https://blog.csdn.net/Jerome_s/article/details/37103171 通过注解方式注入并使用其他EJB或者服务 ...

  10. 学会这 2 点,轻松看懂 MySQL 慢查询日志

    MySQL中的日志包括:错误日志.二进制日志.通用查询日志.慢查询日志等等.这里主要介绍下比较常用的两个功能:通用查询日志和慢查询日志. 1)通用查询日志:记录建立的客户端连接和执行的语句. 2)慢查 ...