hdu 5787 K-wolf Number (数位DP )

Problem Description
Alice thinks an integer x is a K-wolf number, if every K adjacent digits in decimal representation of x is pairwised different.
Given (L,R,K), please count how many K-wolf numbers in range of [L,R].
 

Input
The input contains multiple test cases. There are about 10 test cases.

Each test case contains three integers L, R and K.

1LR1e18
2K5
 

Output
For each test case output a line contains an integer.
 

Sample Input
  
  
1 1 2 20 100 5
 

Sample Output
  
  
1 72
 

(1)前导零的处理


代码1

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
#include <cstdlib>
#include <string>
#include <cmath>
#include <set>
#include <map>
#include <bitset>

#define LL long long

#pragma comment(linker, "/STACK:102400000,102400000")

using namespace std;

const double eps = 1e-9;
const int inf = 0x3f3f3f3f;

int n,m;
LL l,r;
int k;

map<vector<int>,LL> dp[20];

int digit[29];
int tot=0;

bool ok(const vector<int> & ve)
{
    int last = ve[k-1];
    for(int i=0; i<k-1; i++)
    {
        if(last == ve[i])
            return false;
    }

    return true;
}


LL dfs(int pos,vector<int> vec,bool ismax,bool iszero)
{
    if(pos==0)
    {
        return 1LL;
    }

    if(!ismax && dp[pos].count(vec)) return dp[pos][vec];

    LL res=0;

    int ed = ismax? digit[pos] : 9;

    vector<int> nt;
    for(int i=1; i<vec.size(); i++)
    {
        if(!iszero)
            nt.push_back(vec[i]);
        else nt.push_back(-i);
    }

    for(int i=0; i<=ed; i++)
    {
        nt.push_back(i);

        if(ok(nt))
            res += dfs(pos-1,nt,ismax && i==ed,iszero && i==0);
        nt.pop_back();
    }

    return ismax ? res : dp[pos][vec] = res;

}

LL solve(LL x)
{
    tot=0;
    while(x)
    {
        digit[++tot] = x%10;
        x /=10;
    }

    vector<int> vec;
    for(int i=1; i<=k; i++) vec.push_back(-i);

    return dfs(tot,vec,true,true);

}

int main()
{


    for(int i=0; i<20; i++) dp[i].clear();

    while(scanf("%I64d%I64d%d",&l,&r,&k)!=EOF)
    {
        printf("%I64d\n",solve(r) - solve(l-1));
    }
    return 0;
}


代码2

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<map>
#define bug(x) cout<<#x<<" = "<<x<<endl;
using namespace std;

const int maxn = 20;
typedef __int64 LL;

LL l,r;
int k;

int tot=0;
int digit[20];

LL dp[20][110000];
LL mod;
int uu[10];

bool can(LL num,int len)
{
    int t;
    memset(uu,0,sizeof(uu));
    for(int i=0;i<len;i++)
    {
        t = num%10;
        num /=10;
        ++uu[t];
        if(uu[t]>=2) return false;
     }
     return true;
}

LL dfs(int pos,LL num,int len,int flag)
{
    if(pos<=0)
    {
        return 1;
    }

    if(flag && dp[pos][num]!=-1) return dp[pos][num];

    int la = flag ? 9 : digit[pos];

    LL ans=0;
    LL cc;

    for(int i=0;i<=la;i++)
    {
        cc = (num*10 + i)%mod;

        if( !can(cc,min(k,len+1)) ) continue;

        if(len==0)
        {
            if(i==0)
                ans += dfs(pos-1,cc,len,  flag||i!=la);
            else ans += dfs(pos-1,cc,min(k,len+1),flag||i!=la);
        }else{
            ans += dfs(pos-1,cc,min(k,len+1),flag||i!=la);
        }
    }
    if(flag)
        dp[pos][num]=ans;
    return ans;
}

LL solve(LL num)
{
    tot=0;
    while(num){digit[++tot]= num%10;num/=10;}

    return dfs(tot,0,0,0);
}

int main()
{
   
    while(scanf("%I64d%I64d%d",&l,&r,&k)!=EOF)
    { 
        memset(dp,-1,sizeof(dp));
        mod=1;
        for(int i=1;i<=k;i++)
            mod *=10;
        printf("%I64d\n", solve(r)-solve(l-1) );
    }

    return 0;
}






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值