HDU 2089 不要62 (数位DP,入门)
题意:
只要含连续的62,或者含4的车牌号码都是不吉利的,其他都是吉利的组合。问区间[L,R]中有多少个数是吉利的?
思路:
依然是利用树(10进制是十叉树)的思想,统计左边所有子树有多少个数是吉利的。这道题得先打表,就是暴力打表都不会超时,否则可能超时了。暴力打表可以直接将0~106扫一遍直接找到[0->R]中吉利的有几个,利用前缀和就行了。
太暴力就没意思了。先用DP处理出吉利的数量以及最高位以2开头的吉利数量,用dp[i][1]表示i位数的吉利数量,dp[i][2]表示i位数且最高位为2的吉利数量。接下来对每个询问的L和R进行统计,差作为答案。看代码就行了,主要是需要考虑得全面一些,明确这一步统计的到底是表示什么。
1 //#include <bits/stdc++.h> 2 #include <iostream> 3 #include <cstdio> 4 #include <cstring> 5 #include <cmath> 6 #include <map> 7 #include <algorithm> 8 #include <vector> 9 #include <iostream> 10 #define pii pair<int,int> 11 #define INF 0x7f3f3f3f 12 #define LL long long 13 using namespace std; 14 const double PI = acos(-1.0); 15 const int N=10; 16 17 int dp[N][N], bit[N], s, t; 18 void pre_cal() 19 { 20 dp[0][1]=1; 21 for(int i=1; i<=7; i++ ) 22 { 23 dp[i][1]=9*dp[i-1][1]-dp[i-1][2]; //吉利(包括0开头) 24 dp[i][2]=dp[i-1][1]; //最高位含2:已经扣除不吉利的了 25 } 26 } 27 28 29 int cal(int n) //计算区间[0~n]吉利的数量 30 { 31 memset(bit,0,sizeof(bit)); 32 int len=0; 33 while(n) 34 { 35 bit[++len]=n%10; 36 n/=10; 37 } 38 int ans=0, i; 39 for(i=len ;i>0; i--) 40 { 41 ans+=dp[i-1][1]*bit[i]; 42 if(bit[i]>4) ans-=dp[i-1][1]; 43 if(bit[i+1]==6&&bit[i]>2) ans-=dp[i-1][1]; 44 if(bit[i]>6) ans-=dp[i-1][2]; //注意点! 45 if(bit[i+1]==6&&bit[i]==2||bit[i]==4) break; 46 } 47 if(i==0) ans++; //n本身是否吉利? 48 return ans; 49 } 50 51 int main() 52 { 53 //freopen("input.txt","r",stdin); 54 pre_cal(); 55 while(scanf("%d%d",&s,&t), s+t) 56 printf("%d\n",cal(t)-cal(s-1)); 57 return 0; 58 }