题意:
只要含连续的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 }
AC代码
作者:xcw0754