题目:牛牛新买了一本算法书,算法书一共有n页,页码从1到n。牛牛于是想了一个算法题目:在这本算法书页码中0~9每个数字分别出现了多少次?
输入描述: 输入包括一个整数n(1 ≤ n ≤ 1,000,000,000)
输出描述: 输出包括一行10个整数,即0~9这些数字在页码中出现的次数,以空格分隔。行末无空格。
例子:
输入 :999 输出:189 300 300 300 300 300 300 300 300 300
思路:
1.容易相待O(N*lgN)时间复杂度的算法,从1到n遍历,找出每个数中,每个数字出现的次数。
2.假设 N=abcde,如果要计算百位上 x 出现的次数,受三个因素影响:百位上的数字,百位以下的数字,百位以上的数字。
以找 1 的数目为例:
如果百位数字为0(小于1),百位上出现 1 的次数仅由高位决定,比如 12 013,百位出现 1 的情况为 100 ~199 1 100 ~ 1 199 .... 11 100~11 199,一共等于更高位的数字
(12)*当前的位数决定。(12*100=1200)。
如果百位数字为1(等于1),百位上出现 1 的次数为高位和低位共同决定。例如 12 123,受高位影响,有100 ~199 1 100 ~ 1 199 .... 11 100~11 199一共等于更高位的数字
(12)*当前的位数决定。(12*100=1200)。同时受低位影响,百位出现 1 的情况一共 12 100 ~ 12 113 一共14个,等于低位数(13)+1。
如果百位数字为 2~9(大于1),百位上出现 1 的次数仅由高位决定,比如 12 213,百位出现 1 的情况为 100 ~199 1 100 ~ 1 199 .... 12 100~12 199,一共等于更高位的字
加1(12+1)*当前的位数决定。(1300)。
代码:
#include <vector>
#include <iostream>
#include <cmath>
using namespace std;
int count_xNum(int n, int x){
int xCount = 0,j,i=1;
while (j = n / i){
int higher = j / 10;
if (x == 0){
if (higher) higher--; // 排除 00011 这种情况
else break;
}
xCount += higher*i;
int temp = j % 10;
if (temp > x)
xCount += i;
else if (temp == x)
xCount += n-j*i + 1;
i *= 10;
}
return xCount;
}
int main()
{
long long n;
cin >> n;
cout << count_xNum(n, 0);
for (int i = 1; i <= 9; ++i)
cout << " " << count_xNum(n, i);
cout << endl;
return 0;
}