HDU5787 K-wolf Number

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


【题意】给定三个数i,j,k。问i-j之间有多少任意k位数都不相同的数。


【分析】数位dp,用dp[pos][p1][p2][p3][p4]表示当前位为第pos位,前第一位为p4,前第二位为p3,前第三位为p2,前第四位为p1的数的满足条件的数的个数。用特殊的10表示前导0。用dfs进行记忆化搜索。搜索过程中用flg标记前位是否取满以确定当前位的取值上限。


【代码】

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define LL long long
LL dp[20][12][12][12][12];
int dig[20];
LL l,r;
int k;
bool check(int p1,int p2,int p3,int p4,int p5){
    if(k==2)
        return p5!=p4;
    if(k==3)
        return (p5!=p4 && p5!=p3);
    if(k==4)
        return (p5!=p4 && p5!=p3 && p5!=p2);
    return (p5!=p4 && p5!=p3 && p5!=p2 && p5!=p1);
}
LL dfs(int pos,int p1,int p2,int p3,int p4,bool flg){
    if(pos==0)
        return p4!=10;
    if(!flg && dp[pos][p1][p2][p3][p4]!=-1)
        return dp[pos][p1][p2][p3][p4];
    int ed=flg?dig[pos]:9;
    LL ans=0;
    for(int i=0;i<=ed;++i){
        if(i==0 && p4==10)
            ans+=dfs(pos-1,10,10,10,10,flg && i==ed);
        else
            if(check(p1,p2,p3,p4,i))
                ans+=dfs(pos-1,p2,p3,p4,i,flg && i==ed);
    }
    if(!flg)
        dp[pos][p1][p2][p3][p4]=ans;
    return ans;
}
LL cal(LL x){
    if(x<=0)
        return 0;
    LL tmp=x;
    int len=0;
    while(tmp){
        dig[++len]=tmp%10;
        tmp/=10;
    }
    return dfs(len,10,10,10,10,1);
}
int main(){
    while(~scanf("%I64d %I64d %d",&l,&r,&k)){
        memset(dp,-1,sizeof(dp));
        printf("%I64d\n",cal(r)-cal(l-1));
    }
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章