Hdu 2089 不要62 (数位dp入门题目)
题目链接:
题目描述:
给一个区间 [L, R] ,问区间内不含有4和62的数字有多少个?
解题思路:
以前也做过这个题目,但是空间复杂度是n。如果数据范围太大就GG了。今天看了一下数位DP,的确有时间和空间上的优越性。
用数位dp做这个题目的时候,首先要预处理出dp[x][y],代表以y开头的x位数中不含有62和4的数有多少个,在满足条件的情况下状态转移为:dp[x][y] += dp[x-1][k]。又因为对于一个数字x,如果和它位数相同的数字y小于x,那么只需要y数字其中任意一位小于x即可。然后问题就变为求ans([1, r+1]) - ans([1, l])。
1 #include <vector> 2 #include <cstdio> 3 #include <cstring> 4 #include <iostream> 5 #include <algorithm> 6 using namespace std; 7 8 const int maxn = 10; 9 int dp[maxn][maxn]; 10 //dp[x][y] 以y开头的x位数满足题意的个数 11 12 void init () 13 { 14 memset(dp, 0, sizeof(dp)); 15 dp[0][0] = 1; 16 for (int i=1; i<=7; i++)//i位数 17 for (int j=0; j<10; j++)//第i位数 18 for (int k=0; k<10; k++)//第i-1位数 19 { 20 if(j==4 || j==6&&k==2) 21 continue ; 22 dp[i][j] += dp[i-1][k]; 23 } 24 } 25 26 int solve (int n) 27 { 28 int a[maxn], len = 0, ans = 0; 29 while (n) 30 { 31 a[++len] = n % 10; 32 n /= 10; 33 } 34 a[len+1] = 0; 35 36 for (int i=len; i>0; i--) 37 {//枚举后len位的策略 38 for (int j=0; j<a[i]; j++) 39 { 40 if (j==4 || a[i+1]==6&&j==2) 41 continue ; 42 ans += dp[i][j]; 43 } 44 45 if (a[i]==4 || a[i+1]==6 && a[i]==2) 46 break; 47 } 48 return ans; 49 } 50 51 int main () 52 { 53 int n, m; 54 init (); 55 56 while (scanf ("%d %d", &n, &m), n + m) 57 printf ("%d\n", solve(m+1) - solve(n)); 58 return 0; 59 }
本文为博主原创文章,未经博主允许不得转载。