码迷,mamicode.com
首页 > 其他好文 > 详细

hdu4352(数位dp)

时间:2015-02-01 13:27:27      阅读:246      评论:0      收藏:0      [点我收藏+]

标签:

 

题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=4352

题意:求区间L到R之间的数A满足A的的数位的最长递增序列的长度为K的数的个数。

分析:数位dp,dp[i][j][k]表示后面还有i位,此时状态为k,最长上升子序列为j时的总数(在非限制即0~9任意填的情况下)。

要真正理解LIS的本质才能解这题,state状态维护的是前面上升子序列中出现的数字(二进制状态压缩),前面设状态为167(state为001100001),假设此时i=2,维护上升序列长度为3,应该把6变为2(此时state为001000011)127,最长上升子序列长度不变,但能让后面更多的数加进来。

这题还得注意前导0的影响。

技术分享
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <queue>
#include <cstdlib>
#include <stack>
#include <vector>
#include <set>
#include <map>
#define LL long long
#define mod 100000000
#define inf 0x3f3f3f3f
#define eps 1e-9
#define N 100010
#define FILL(a,b) (memset(a,b,sizeof(a)))
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
int dig[30];
LL dp[25][11][1100];
int k;//当前位,上升子序列出现的数字的状态,长度,是否上限,是否前导0
LL dfs(int pos,int state,int num,int limit,int fzore)
{
    if(!pos)
    {
        return k==num;
    }
    if(!limit&&~dp[pos][k][state])return dp[pos][k][state];
    int len=limit?dig[pos]:9;
    LL ans=0;
    for(int i=0;i<=len;i++)
    {
        if((1<<i)>state)
            ans+=dfs(pos-1,(fzore&&!i)?0:state|(1<<i),(fzore&&!i)?0:num+1,limit&&i==len,fzore&&!i);
        else if(state&(1<<i))
            ans+=dfs(pos-1,state,num,limit&&i==len,fzore&&!i);
        else
        {
            for(int j=i+1;j<=9;j++)
            if(state&(1<<j))
            {
                ans+=dfs(pos-1,state-(1<<j)|(1<<i),num,i==len&&limit,fzore&&!i);
                break;
            }
        }
    }
    if(!limit)dp[pos][k][state]=ans;
    return ans;
}
LL solve(LL x)
{
    int len=0;
    while(x)
    {
        dig[++len]=x%10;
        x/=10;
    }
    return dfs(len,0,0,1,1);
}
int main()
{
    int T,cas=1;
    FILL(dp,-1);
    scanf("%d",&T);
    while(T--)
    {
        LL a,b;
        scanf("%I64d%I64d%d",&a,&b,&k);
        printf("Case #%d: ",cas++);
        printf("%I64d\n",solve(b)-solve(a-1));
    }
}
View Code

 

hdu4352(数位dp)

标签:

原文地址:http://www.cnblogs.com/lienus/p/4265430.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!