问题描述
牛牛新买了一本算法书,算法书一共有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
分析
参考《编程之美》和《剑指offer》的算法。
假设一个数N被表示为XDY,X和Y都是一串数字,长度为[0-∞];D是一个数字,大小为[0-9]。要注意的是,当X的长度为0,即D是最高位数字时,D不能为0。
现在要分析[1-N]这N个数在D位上出现数字d的次数C。我们可以举一个具体的例子,当X=12,Y=56时,N=12D56,设d=1。根据D的大小情况,分下面三种情况讨论:
-
D < 1
即D=0,此时在D位上出现1的情况有:100-199,1100-1199,2100-2199,...,11100-11199,总共1200个; -
D = 1
此时在D位上出现1的情况有:100-199,1100-1199,2100-2199,...,11100-11199,12100-12156,总共1200+156+1个; -
d > 1
此时在D位上出现1的情况有:100-199,1100-1199,2100-2199,...,11100-11199,12100-12199,总共1300个;
设Y的位数为pY。至此我们可以得出结论:当D<1时,C=X10^pY;当D=1时,C=X10pY+Y+1;当D>1时,C=(X+1)*10pY。
同理,这个结论对d∈[1,9]都适用。当d=0时,pY项改成pY-1即可。因为0不能作为最高项。例如上面D的三种情况,如果d=1,每种情况都有100-199;但是如果d=0,则不能出现000-099,这样就正好少了X*10项。
note
- 多列几个具体的例子,找找规律;
- 要善于分类讨论。
代码
字符串处理后转数字
#include <cstdio>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
long long countDigit(const string &str, int i, int j)
{
int p = str.size() - i;
int d = str[p - 1] - '0';
string upperStr = str.substr(0, p - 1);
string lowerStr = str.substr(p, i);
long long upperNum = upperStr.empty() ? 0 : stoll(upperStr);
long long lowerNum = lowerStr.empty() ? 0 : stoll(lowerStr);
if (j == 0) upperNum--;
if (d < j)
return upperNum * pow(10, i);
if (d == j)
return upperNum * pow(10, i) + lowerNum + 1;
return (upperNum + 1) * pow(10, i);
}
int main()
{
char str[11];
scanf("%s", str);
string num(str);
vector<long long> cnt(10, 0);
for (int i = 0; i < num.length(); i++)
for (int j = 0; j < 10; j++)
cnt[j] += countDigit(str, i, j);
printf("%d", cnt[0]);
for (int i = 1; i < 10; i++)
printf(" %d", cnt[i]);
return 0;
}
数字计算
#include<iostream>
using namespace std;
int count(int n, int x)
{
int cnt = 0;
for (int i = 1, j; j = n / i; i *= 10)
{
int high = j / 10;
int low = n - j * i;
int digit = j % 10;
if (x == 0) high--;
cnt += high * i;
if (digit > x)
cnt += i;
else if (digit == x)
cnt += low + 1;
}
return cnt;
}
int main()
{
int n;
cin >> n;
cout << count(n, 0);
for (int i = 1; i <= 9; i++)
cout << " " << count(n, i);
return 0;
}
网友评论