HDOJ 5787 K-wolf Number 数位DP

数位DP的一道所谓的水题!

但是呢,必须得胆子大!

题意:求区间【L,R】中有多少个满足条件的十进制数

条件是:任意连续K个数值都不相同,K=2,3,4,5


dp最难的是设计状态和状态转移啊!

K很小,所以可以每一个有意义的数位都来一维来表示呗

dp[pos][p1][p2][p3][p4]

pos表示当前位,p4表示前一位。这里要考虑前导0的情况,p4=10的时候表示前一位为0

然后呢,最特殊的情况是:全是0的情况


转移呢,枚举即可

判断条件要根据K来说咯,如果K=2,那么当前枚举的这一位不等于p4

K=3,4,5是同理的


代码如下:

#include<bits/stdc++.h>
using namespace std;

#define LL __int64

const int maxn=25;
int K,digit[maxn];
LL dp[maxn][11][11][11][11];

bool check(int p1,int p2,int p3,int p4,int u){
    if (K==2) return u!=p4;
    else if (K==3) return u!=p4&&u!=p3;
    else if (K==4) return u!=p4&&u!=p3&&u!=p2;
    else return u!=p4&&u!=p3&&u!=p2&&u!=p1;
}

LL dfs(int pos,int p1,int p2,int p3,int p4,bool flag){
    if (pos==0) return p4!=10;
    if (flag&&dp[pos][p1][p2][p3][p4]!=-1) return dp[pos][p1][p2][p3][p4];
    LL res=0;
    int maxnum=flag?9:digit[pos];
    for(int i=0;i<=maxnum;i++){
        if (p4==10&&i==0)
            res+=dfs(pos-1,10,10,10,10,flag||i<maxnum);
        else if (check(p1,p2,p3,p4,i))
            res+=dfs(pos-1,p2,p3,p4,i,flag||i<maxnum);
    }
    if (flag) dp[pos][p1][p2][p3][p4]=res;
    return res;
}

LL calc(LL x){
    int len=0;
    while(x){
        digit[++len]=x%10;
        x/=10;
    }
    return dfs(len,10,10,10,10,0);
}

int main(){
    //freopen("input.txt","r",stdin);
    LL L,R;
    while(scanf("%I64d%I64d%d",&L,&R,&K)!=EOF){
        memset(dp,-1,sizeof(dp));
        printf("%I64d\n",calc(R)-calc(L-1));
    }
    return 0;
}

注意:

在数位dp分隔数位的时候

一定是digit【++len】而不是digit【len++】

一方面是因为最后的初始边界是len==0,就算 改成len==-1也是不行的

因为:dp的初始化会导致有问题

全部评论

相关推荐

10-28 11:04
已编辑
美团_后端实习生(实习员工)
一个2人:我说几个点吧,你的实习经历写的让人觉得毫无含金量,你没有挖掘你需求里的 亮点, 让人觉得你不仅打杂还摆烂。然后你的简历太长了🤣你这个实习经历看完,估计没几个人愿意接着看下去, sdk, 索引这种东西单拎出来说太顶真了兄弟,好好优化下简历吧
点赞 评论 收藏
分享
拒绝无效加班的小师弟很中意你:求职意向没有,年龄、课程冗余信息可以删掉,需要提升项目经历。排版需要修改。
点赞 评论 收藏
分享
头像
11-27 14:28
长沙理工大学
刷算法真的是提升代码能力最快的方法吗?&nbsp;刷算法真的是提升代码能力最快的方法吗?
牛牛不会牛泪:看你想提升什么,代码能力太宽泛了,是想提升算法能力还是工程能力? 工程能力做项目找实习,算法也分数据结构算法题和深度学习之类算法
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务