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

HDU 5787 K-wolf Number(数位DP)

时间:2016-11-17 01:30:08      阅读:163      评论:0      收藏:0      [点我收藏+]

标签:namespace   space   href   ems   pos   include   题目   pre   之间   

 

【题目链接】 http://acm.hdu.edu.cn/showproblem.php?pid=5787

 

【题目大意】

  求区间【L,R】内十进制数相邻k位之间不相同的数字的个数。

 

【题解】

   很显然的数位dp,但是状态不知道该怎么转移,然后发现了递归数位DP这种神奇的姿势,每次记录前k位的数字,然后枚举下一位能用的数字,递归即可。

 

【代码】

#include <cstdio>
#include <algorithm>
#include <cstring> 
using namespace std;
typedef long long ll;
const int N=25,M=10005;
int bit[N],pw[5],k;
ll dp[N][M][2][2],l,r;
ll DP(int d,int x,bool f,bool lim){
    int c[5];
    if(d==-1)return 1;
    ll &ret=dp[d][x][f][lim];
    if(~ret)return ret; ret=0;
    int st=k-1,y=x,pos=0;
    for(int i=0;i<k;i++)c[i]=y%10,y/=10;
    if(!f){while(!c[st]&&st>=0)st--;}
    for(int i=st;i>=0;i--)pos|=1<<c[i];
    int up=lim?bit[d]:9;
    for(int i=0;i<=up;i++){
        if(pos>>i&1)continue;
        if(f)ret+=DP(d-1,(x-pw[k-1]*c[k-1])*10+i,f,lim&&i==up);
        else if(st==-1&&!i)ret+=DP(d-1,0,0,lim&&i==up);
        else ret+=DP(d-1,x*10+i,st==k-2,lim&&i==up);
    }return ret;
}
ll Cal(ll x){
    if(!x)return 1;int cnt=0;
    while(x)bit[cnt++]=x%10,x/=10;
    memset(dp,-1,sizeof(dp));
    return DP(cnt-1,0,0,1);
}
int main(){
    for(int i=pw[0]=1;i<5;i++)pw[i]=pw[i-1]*10;
    while(~scanf("%lld%lld%d",&l,&r,&k)){
        k--;printf("%lld\n",Cal(r)-Cal(l-1));
    }return 0;
}

  

HDU 5787 K-wolf Number(数位DP)

标签:namespace   space   href   ems   pos   include   题目   pre   之间   

原文地址:http://www.cnblogs.com/forever97/p/hdu5787.html

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