题目传送门

解题思路:

本题实质是求一个小于一个数的所有正整数中,没有4或62的数字个数,我们先将要求的范围m分解成一个数组,从高位开始枚举,只要最高位小于m的最高位,其实后面写任意数都是方案之一(除含4或62),固定最高位后,再枚举次高位,以此类推......而对于后面任意数的方案数,可以用f数组做预处理.

AC代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 
 5 using namespace std;
 6 
 7 int n,m;
 8 long long f[11][11],d[10];
 9 //f[i][j]表示到第i位时有j个1的方案数 
10 
11 inline void dp() {
12     f[0][0] = 1;
13     for(int i = 1;i <= 9; i++)
14         for(int j = 0;j <= 9; j++)
15             for(int k = 0;k <= 9; k++)
16                 if(j != 4 && !(j == 6 && k == 2))//不能出现4或62 
17                     f[i][j] += f[i-1][k];
18 }
19 
20 inline long long C(int k) {//求小于k的范围内有几个符合的 
21     long long tot = 0,ans = 0;
22     memset(d,0,sizeof(d));
23     while(k != 0) {
24         d[++tot] = k % 10;
25         k /= 10;
26     }
27     for(int i = tot;i >= 1; i--) {//枚举最高位的位数 
28         for(int j = 0;j <= d[i] - 1; j++)//枚举当前最高位的数字 
29             if(j != 2 || d[i+1] != 6)
30                 ans += f[i][j];
31         if(d[i] == 4 || (d[i+1] == 6 && d[i] == 2))//已经出现了4或62,则后面无论填什么数,都是不合法的 
32             break;
33     }
34     return ans;
35 }
36 
37 int main() {
38     dp();
39     while(true) {
40         scanf("%d%d",&n,&m);
41         if(n == 0 || m == 0) return 0;
42         printf("%lld\n",C(m + 1) - C(n));
43     }
44     return 0;
45 }
扫码关注我们
微信号:SRE实战
拒绝背锅 运筹帷幄

SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。