HDU 2089 不要62:
题目大意是给你一个区间,让你统计这个区间里不包含 4 和 62 的数字的个数。
最朴素的思路是:
对于每个区间 [l, r],遍历所有在区间 [l, r] 里的数字,然后检查每个数字是不是合法(没有 4 和 62 ),如果合法答案加一。
代码如下:
#include<bits/stdc++.h>
using namespace std;
bool check(int a) {
while (a) {
int b = a % 10;
int c = a % 100;
if (b == 4 || c == 62)
return false;
a /= 10;
}
return true;
}
int main() {
int n, m;
while (cin >> n >> m) {
int sum = 0;
if (n == 0 && m == 0)
return 0;
for (int i = n; i <= m; i++) {
if (check(i))
sum++;
}
cout << sum << endl;
}
return 0;
}
对于本题,上面的代码是可以通过的( 998ms 险过),本题时限 1000ms,时间复杂度是非常高的。
引入数位的概念(个位、十位、百位 ... ),有了数位,就可以换一种方式遍历数字,即:
比如对于 [1, 234] 这个区间,就可以按数位去遍历。
遍历百位数,如果百位数小于这一位的最大值 2 ,那么它的的下一位的最大值为 9 ,否则它的下一位最大值就为 3。以此类推,遍历十位数,如果十位数小于 3,那么它的下一位最大值为 9,否则为 4。
对于这种遍历数字的方法,当区间最小值为 1 的时候是容易的,但如果最小值大于 1,遍历的时候不但要考虑数位的最大值,还要考虑数位的最小值,遍历起来会麻烦许多,因此,可以利用前缀和的思想,求 F(n - 1) = { 1 - ( n - 1 ) 的数字数 } 和 F(m) = { 1 - m 的数字数 },然后 ANS = F(m) - F(n - 1)。
那样就可以根据上面的思路写出 统计一个区间里数字个数 的遍历数位式的代码:
统计区间里数字个数(错误):
#include <bits/stdc++.h>
using names