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;
}