hdu4352(数位DP + LIS(nlogn))
题目描述:
给定一个区间中,将区间的每一个数看成一个字符串,求这个区间内每个字符串的最大上升
子序列等于k的个数。
可以采用nlogn的LIS(用一个C数组记录长度为i的最大上升子序列的结尾最小值),
所以可以采用dfs暴力枚举每一个数,并且由于数的长度最大为18位,
所以c数组可以用一个状态数表示。
dp[len][state][k],代表长度为len的数,c数组状态为state,上升子序列长度等于k的个数。
为什么要加k这一维?因为如果有多组询问,k不相同,那么就不能用之前计算过的dp[len][state]状态,
它保存的其实是,上升子序列长度等于之前k的个数。
可以记忆化的理由:分析到如果不同数的前缀对C数组产生的一样,那么两者等价,那么可以记忆化。
个人理解:其实数位DP考虑记忆化,就要从不同前缀对之后len位的影响考虑。
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
using namespace std;
#define LL long long
LL dp[][<<][]; //长度为30,最大上升子序列状态为s,是否有等于k的个数
int digit[];
int K;
int bit(int state)
{
int cnt=;
while(state>)
{
if(state & ==)
cnt++;
state>>=;
}
return cnt;
} int solve(int state,int i)
{
int j;
int ok=;
for(j=i;j<=;j++)
{
if(state & (<<j))
{
ok=; break;
}
}
int s;
if(ok==)
s=( state ^ (<<j) )| (<<i);
else
s=state | (<< i);
return s;
} LL dfs(int len,int state,bool z,bool fp)
{
if( len== )
return bit(state)==K;
if(!fp && dp[len][state][K] != -)
return dp[len][state][K];
LL ret = ;
int fpmax = fp ? digit[len] : ;
for(int i=;i<=fpmax;i++)
{
int s=solve(state,i);
ret += dfs(len-,(z&&(i==)) ? : s, z&&(i==) ,fp && i == fpmax);
}
if(!fp)
dp[len][state][K] = ret;
return ret;
} LL f(LL n)
{
int len = ;
while(n)
{
digit[++len] = n % ;
n /= ;
}
return dfs(len,,,true);
} int main()
{
//freopen("test.txt","r",stdin);
LL a,b;
int t,Case=;
scanf("%d",&t);
memset(dp,-,sizeof(dp));
while(t--)
{
scanf("%lld%lld%d",&a,&b,&K);
if(a==b)
printf("Case #%d: %d\n",++Case,);
printf("Case #%d: %lld\n",++Case,f(b)-f(a-));
} return ;
}
hdu4352(数位DP + LIS(nlogn))的更多相关文章
- hdu4352 XHXJ's LIS(数位DP + LIS + 状态压缩)
#define xhxj (Xin Hang senior sister(学姐)) If you do not know xhxj, then carefully reading the entire ...
- HDU 4352 XHXJ's LIS 数位dp lis
目录 题目链接 题解 代码 题目链接 HDU 4352 XHXJ's LIS 题解 对于lis求的过程 对一个数列,都可以用nlogn的方法来的到它的一个可行lis 对这个logn的方法求解lis时用 ...
- HDU 4352 XHXJ's LIS (数位DP+LIS+状态压缩)
题意:给定一个区间,让你求在这个区间里的满足LIS为 k 的数的数量. 析:数位DP,dp[i][j][k] 由于 k 最多是10,所以考虑是用状态压缩,表示 前 i 位,长度为 j,状态为 k的数量 ...
- HDU 4352 - XHXJ's LIS - [数位DP][LIS问题]
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4352 Time Limit: 2000/1000 MS (Java/Others) Memory Li ...
- hdu4352 数位dp+状态压缩+一个tip
按照nlogn求lis的方法,把lis的状态压缩了,每次新加一个数就把它右边第一个数的位置置为0,然后把这个数加进去 一个需要注意的地方,如果前面都是0,那么状态s中代表0的位置不可以是1,因为这种情 ...
- HDU 4352 区间的有多少个数字满足数字的每一位上的数组成的最长递增子序列为K(数位DP+LIS)
题目:区间的有多少个数字满足数字的每一位上的数组成的最长递增子序列为K 思路:用dp[i][state][j]表示到第i位状态为state,最长上升序列的长度为k的方案数.那么只要模拟nlogn写法的 ...
- HDU 4352 数位dp
XHXJ's LIS Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
- hdu4352 XHXJ's LIS[数位DP套状压DP+LIS$O(nlogn)$]
统计$[L,R]$内LIS长度为$k$的数的个数,$Q \le 10000,L,R < 2^{63}-1,k \le 10$. 首先肯定是数位DP.然后考虑怎么做这个dp.如果把$k$记录到状态 ...
- HDU4352 XHXJ's LIS 题解 数位DP
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4352 题目大意: 求区间 \([L,R]\) 范围内最长上升子序列(Longest increasin ...
随机推荐
- [codeforces724D]Dense Subsequence
[codeforces724D]Dense Subsequence 试题描述 You are given a string s, consisting of lowercase English let ...
- [luoguP2704] 炮兵阵地(状压DP)
传送门 可以事先把每一行的所有状态处理出来,发现每一行的状态数最多不超过60个 f[i][j][k]表示前i行,第i行为状态j,第i-1行为状态k的最优解 #include <vector> ...
- 【BFS+优先级队列】Rescue
https://www.bnuoj.com/v3/contest_show.php?cid=9154#problem/I [题意] 给定一个n*m的迷宫,A的多个小伙伴R要去营救A,问需要时间最少的小 ...
- 后缀排序(codevs 1500)
题目描述 Description 天凯是MIT的新生.Prof. HandsomeG给了他一个长度为n的由小写字母构成的字符串,要求他把该字符串的n个后缀(suffix)从小到大排序. 何谓后缀?假设 ...
- msp430项目编程01
msp430中项目---点阵LED显示 1.点阵LED介绍 2.代码(直接使用引脚驱动) 3.代码(使用芯片驱动) 4.项目总结 msp430项目编程 msp430入门学习
- Cooking Schedule Problem Code: SCHEDULE(优先队列)
Cooking Schedule Problem Code: SCHEDULE Chef is a well-known chef, and everyone wishes to taste his ...
- CodeForces 593A 2Char
暴力. #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> u ...
- HUD——1083 Courses
HUD——1083 Courses Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Ot ...
- 2017CodeM初赛A场
A.最长树链(loj6159) 分析: 对于每个质因数,取出所有是它倍数的点组成一个树,然后找最长路径 每个数操作次数是其质因数的个数 所以总的复杂度不超过O(nlogA) B.二分图染色(loj61 ...
- Win7查看本地是否安装JDK及安装路径的方法
工具/原料 win7 方法/步骤 1 开始->点击运行,输入:cmd 2 然后在命令提示符中,输入:java -version 假如看到有版本提示那么安装成功 3 假如忘记了java ...