[编程题]页码统计
Posted Bouygues
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[编程题]页码统计相关的知识,希望对你有一定的参考价值。
题目
牛客网 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题。
以上是关于[编程题]页码统计的主要内容,如果未能解决你的问题,请参考以下文章