hdu 5787 K-wolf Number 数位dp

K-wolf Number

题目连接:

http://acm.hdu.edu.cn/showproblem.php?pid=5787

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.

1≤L≤R≤1e18
2≤K≤5

Output

For each test case output a line contains an integer.

Sample Input

1 1 2
20 100 5

Sample Output

1
72

Hint

题意

问你[L,R]里面有多少个数,其中相同的数字至少相差k位。

题解:

显然的数位dp,我们记录前k-1个数是哪些就好了。

空间要滚动一下。

代码

#include <bits/stdc++.h>
#define rep(a,b,c) for(int (a)=(b);(a)<=(c);++(a))
#define drep(a,b,c) for(int (a)=(b);(a)>=(c);--(a))
#define pb push_back
#define mp make_pair
#define sf scanf
#define pf printf
#define two(x) (1<<(x))
#define clr(x,y) memset((x),(y),sizeof((x)))
#define dbg(x) cout << #x << "=" << x << endl;
#define lowbit(x) ((x)&(-x))
const int mod = 1e9 + 7;
int mul(int x,int y){return 1LL*x*y%mod;}
int qpow(int x , int y){int res=1;while(y){if(y&1) res=mul(res,x) ; y>>=1 ; x=mul(x,x);} return res;}
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;}
using namespace std;
const int maxn = 200 + 15;
char str[maxn];
int len , bit[ 100500 ] , K , ten[10] ;
vector < int > number[ 100050 ];
long long dp[2][2][2][6][ 10050 ];

inline void up(long long & x , long long v){ x += v; }

void init(){
    number[0].pb( 0 );
    ten[0] = bit[0] = 1;
    for(int i = 1 ; i < 8 ; ++ i) ten[i] = ten[i - 1] * 10;
    for(int i = 1 ; i <= 10000 ; ++ i){
        int x = i;
        while( x > 0 ){
            number[i].pb( x % 10 );
            bit[i] |= ( 1 << ( number[i].back() ) );
            x /= 10;
        }
        reverse( number[i].begin() , number[i].end() );
    }
}

pair < int , int > Transform( int st , int l , int add ){
    int rs = st * 10 + add;
    if( l < K ) return mp( rs , l + 1 );
    else{
        if( rs >= ten[K] ) return mp( rs - ten[K] * number[st][0] , K ) ;
        else return mp( rs , K );
    }
}

long long solve( long long x ){
    if( x == 0 ) return 1LL;
    len = 0;
    while( x > 0 ){
        str[ ++ len ] = (x % 10) + '0';
        x /= 10;
    }
    reverse( str + 1 , str + len + 1 );
    int cur = 0;
    clr( dp[cur] , 0 );

    // 第 i 位 , 下界标志 f1 , 前导零标记 f2 , 状态 st 的位数 , 状态 st

    dp[cur][0][1][0][0] = 1;
    for(int i = 1 ; i <= len ; ++ i){
        int pre = cur ; cur ^= 1;
        clr( dp[cur] , 0 );
        for(int f1 = 0 ; f1 < 2 ; ++ f1)
            for(int f2 = 0 ; f2 < 2 ; ++ f2)
                for(int l = 0 ; l <= K ; ++ l)
                    for(int st = 0 ; st < 10000 ; ++ st)
                        if( dp[pre][f1][f2][l][st] ){
                            int ed = f1 ? 9 : str[i] - '0';
                            for(int add = 0 ; add <= ed ; ++ add){
                                int newf1 = f1 | ( add < ed );
                                int newf2;
                                if( f2 == 0 ) newf2 = 0;
                                else{
                                    if( add == 0 ) newf2 = 1;
                                    else newf2 = 0;
                                }
                                if( ((bit[st] >> add) & 1)==1 && f2 ==0 ) continue;
                                if( number[st].size() < l && add == 0 ) continue; // 有前导 0 
                                if( f2 == 1 && add == 0 ) up( dp[ cur ][ newf1 ][ 1 ][ 0 ][ 0 ] , dp[pre][f1][f2][l][st] );
                                else{
                                    pair < int , int > rp = Transform( st , l , add );
                                    up( dp[ cur ][ newf1 ][ 0 ][ rp.second ][ rp.first ] , dp[pre][f1][f2][l][st] );
                                }
                            }
                        }
    }
    long long ans = 0;
    for(int f1 = 0 ; f1 < 2 ; ++ f1) for(int f2 = 0 ; f2 < 2 ; ++ f2) for(int l = 0 ; l <= K;  ++ l) for(int st = 0 ; st < 10000 ; ++ st) up( ans , dp[cur][f1][f2][l][st] );
    return ans;
}

int main(int argc,char *argv[]){
    init();
    long long L , R ;
    while(~sf("%I64d%I64d%d",&L,&R,&K)){
        -- K;
        pf("%I64d\n" , solve( R ) - solve( L - 1 )) ;
    }
    return 0;
}
    原文作者:qscqesze
    原文地址: https://www.cnblogs.com/qscqesze/p/5730394.html
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞