[编程题]页码统计
题目
牛客网 https://www.nowcoder.com/questionTerminal/3a003cb6a3174ef9835fa603e01d8b52
牛客网原题:
牛牛新买了一本算法书,算法书一共有n页,页码从1到n。牛牛于是想了一个算法题目:在这本算法书页码中0~9每个数字分别出现了多少次?
思路
按位数某个数字出现过多少次。也就是说,固定某一位上的某个数,看看此时有几种情况。
举个栗子:
对统计1~785012中5出现的个数
我们先考虑5在低位第三位出现的次数,我们就将第三位固定为5:XXX5XX。
此时,问题就转化为,“X”处一共有多少种组合方式。
高位的3位可以从000到785之间,低位的2位可以从00到99之间。
但是,当高3位为785时,7855XX无论如何都超过了785012,因此,高三位可以选择的只有000~784(共785个数字),高三位和低二位一共有785*100种组合方式。
我们再考虑5在低位第四位出现的次数,我们就将第四位固定为5:XX5XXX。
与前面相同,高位的二位可以从00到78之间,低位的三位可以从000到999之间。
当高位是00到77时,与前面一种情况是相同的,一共可以组合出78*1000种情况。
当高位是78时,785XXX就有超过785012的可能了,后三位的选择局限在000到012之间,共13中情况。
两者结合就是:78*1000+13
最后考虑5在低位第5位出现的次数,我们就将第五位固定为5:X5XXXX。
与前面相同,最高位可以从0取到7,低四位可以从0000取到9999.
当最高位为0到6时,与第一种情况相同,一共可以组合出7*10000中情况。
当高位是7时,与前面的情况不同的是,75XXXX是不会越界的,后四位可以从0000取到9999,所以可以组合出10000中情况。
两者结合就是:7*10000+10000
但是,当统计0的个数时,情况又有所不同。还用785012讨论,如果我们要统计低位低2位出现0的次数,按照前面的方法,我们可能把00000X讨论进来,认为这也是第二位出现0的情况,但是这个数只能表示为X,它的第二位根本不存在。
因此,针对0这种情况,我们需要单独讨论,只需要分成两类,不可能存在当前位小于0的情况,不过每次高位的取值要把全0的情况剔除。
代码
我的代码如下
#include <iostream>
using namespace std;
//count the bit of N, and the low_n/high_n at lowest bit/highest bit
int countBit(int n, int *low_n, int *high_n)
{
int t = n;
int res = 0;
int high;
*low_n = t % 10;
while (t > 0)
{
res++;
high = t % 10;
t = t / 10;
}
*high_n = high;
return res;
}
int pow(int n, int x)
{
int t = 1;
for (int i = 0; i < x; i++)
t *= n;
return t;
}
int main(int argc, char** argv)
{
int n;
int i, j, k, t;
int low, high, len; //low: 0th number; high: len-th number; len: lenghth of n;
int lown, highn, curn; //highn: number before current bit, lown: after curent bit; curn: current bit;
int result[10];
cin >> n;
len = countBit(n, &low, &high);
for (i = 0; i < 10; i++) result[i] = 0;
for (i = 0; i < len; i++)
{
t = pow(10, i);
highn = n / (t * 10); lown = n%t; curn = (n/t) % 10;
for (j = 0; j < 10; j++)
{
if (j == 0)
{
if (i == len - 1)
continue;
if (curn == 0)
result[j] += (highn - 1)*t + (lown + 1);
else
result[j] += highn * t;
}
else if (j == curn)
result[j] += highn * t + (lown + 1);
else if (j>curn)
result[j] += highn * t;
else //j<curn && j!=0
result[j] += (highn+1) * t;
}
}
//output
cout << result[0];
for (i = 1; i < 10; i++)
cout << " " << result[i];
return 0;
}
PS,自己写pow函数的原因 - 公司的算法考试不允许使用stdlib和stl,所以习惯自己写。
这是我的第一个newcoder题。

浙公网安备 33010602011771号