HDU-5787 K-wolf Number(数位DP)

题目

如果一个数 n ,每 k 个连续的数位各位数字均不相同,则称这个数为 k w o l f 数,求一个区间 [ a , b ] k w o l f 数的个数。
1 a b 1 10 18
2 k 5

思路

比较浅显,只用保存前面枚举到的数即可,前导零按照惯例都是需要特判的。

代码

#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define FOR(i,x,y) for(int i=(x);i<=(y);i++)
#define DOR(i,x,y) for(int i=(x);i>=(y);i--)
typedef long long LL;
using namespace std;
LL dp[20][11][11][11][11];
int num[20],wolf;

bool check(int f1,int f2,int f3,int f4,int t)
{
    if(wolf==2)return f1!=t;
    else if(wolf==3)return f1!=t&&f2!=t;
    else if(wolf==4)return f1!=t&&f2!=t&&f3!=t;
    else if(wolf==5)return f1!=t&&f2!=t&&f3!=t&&f4!=t;
}
LL dfs(int k,int f1,int f2,int f3,int f4,bool ismax)
{
    if(k==0)return 1;
    if(!ismax && ~dp[k][f1][f2][f3][f4])return dp[k][f1][f2][f3][f4];
    int maxer=ismax?num[k]:9;
    LL res=0;
    FOR(i,0,maxer)
    {
        if(f1+f2+f3+f4==40 && i==0)res+=dfs(k-1,f1,f2,f3,f4,ismax&&i==maxer);
        else if(check(f1,f2,f3,f4,i))
            res+=dfs(k-1,i,f1,f2,f3,ismax&&i==maxer);
    }
    if(!ismax)dp[k][f1][f2][f3][f4]=res;
    return res;
}
LL solve(LL x)
{
    int p=0;
    while(x)
    {
        num[++p]=x%10;
        x/=10;
    }
    return dfs(p,10,10,10,10,1);
}

int main()
{
    LL L,R;
    while(~scanf("%lld%lld%d",&L,&R,&wolf))
    {
        memset(dp,-1,sizeof(dp));
        printf("%lld\n",solve(R)-solve(L-1));
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/paulliant/article/details/80465344
今日推荐