問題描述
牛牛新買了一本算法書,算法書一共有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;
}