http://acm.split.hdu.edu.cn/showproblem.php?pid=5787
题意:
给出一个范围[l,r]和整数k,求出在该范围的数在十进制每k个相邻的数都不同的数的个数。
思路:
看题意就是挺明显的数位dp,一开始不想开5维数组,想用哈希记录状态,不过错了,可能是姿势不太对。。然后就开了5维数组,因为K最多就5嘛,注意好前导0的问题即可。
1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<cstdio> 5 #include<vector> 6 #include<stack> 7 #include<queue> 8 #include<cmath> 9 #include<map> 10 #include<set> 11 using namespace std; 12 typedef long long ll; 13 typedef pair<int,int> pll; 14 const int INF = 0x3f3f3f3f; 15 const int maxn = 1e6 + 5; 16 17 ll L,R; 18 int K; 19 int dig[30]; 20 ll dp[30][11][11][11][11]; 21 22 bool check(int pre1,int pre2,int pre3,int pre4,int x) 23 { 24 if(K==2) return x!=pre4; 25 else if(K==3) return x!=pre4 && x!=pre3; 26 else if(K==4) return x!=pre4 && x!=pre3 && x!=pre2; 27 else return x!=pre4 && x!=pre3 && x!=pre2 && x!=pre1; 28 } 29 30 ll dfs(int pos, int pre1, int pre2, int pre3, int pre4, int lead ,int limit) 31 { 32 if(pos==-1) return lead!=1; 33 if(!limit && dp[pos][pre1][pre2][pre3][pre4]!=-1) return dp[pos][pre1][pre2][pre3][pre4]; 34 int up=limit?dig[pos]:9; 35 ll tmp = 0; 36 for(int i=0;i<=up;i++) 37 { 38 if(lead && i==0) tmp+=dfs(pos-1,pre1,pre2,pre3,pre4,lead,limit&&i==dig[pos]); 39 else if(check(pre1,pre2,pre3,pre4,i)) 40 tmp+=dfs(pos-1,pre2,pre3,pre4,i,0,limit&&i==dig[pos]); 41 } 42 if(!limit) dp[pos][pre1][pre2][pre3][pre4]=tmp; 43 return tmp; 44 } 45 46 ll solve(ll x) 47 { 48 int pos=0; 49 while(x) 50 { 51 dig[pos++]=x%10; 52 x/=10; 53 } 54 return dfs(pos-1,10,10,10,10,1,1); 55 } 56 57 int main() 58 { 59 //freopen("in.txt","r",stdin); 60 while(~scanf("%lld%lld%d",&L,&R,&K)) 61 { 62 memset(dp,-1,sizeof(dp)); 63 printf("%lld ",solve(R)-solve(L-1)); 64 } 65 return 0; 66 }