在王晓东编著的《算法设计与实验题解》中看到的这个问题,问题描述如下:
一本书的页码从自然数1开始顺序编码直到自然数n。书的页码按照通常的习惯编排,每个页码都不含多余的前导数字0。例如第6页用6表示而不是06或006。数字统计问题要求对给定书的总页码,计算出书的全部页码中分别用到多少次数字0,1,2,3,.....9。
这个题目有个最容易想到的n*log10(n)的算法。这是自己写的复杂度为O(n*log10(n))的代码:
int n; int c[10];//计数 void calc() { for(int i=1;i<=n;i++) { int j=i; do { c[j%10]++; j/=10; }while(j!=0); } for(int i=0;i<10;i++) cout<<c[i]<<endl; } int main() { while(cin>>n) { calc(); } return 0; }
写了个脚本来处理测试数据:
t=`find test -type f` mkdir answer1 for i in $t; do echo $i pos=${#i}-4 echo ${i:$pos:1} k=${i:$pos:1} ./count < $i > answer1/count${k}.out done
formdos answer/* 转换编码
diff -ru answer answer1
更优算法;
http://blog.csdn.net/jcwkyl/article/details/3009244
考察由0,1,2...9组成的所有n位数。从n个0到n个9共有10^n个n位数。在这10^n个n位数中,0,1,2.....9每个数字使用次数相同,设为f(n)。f(n)满足如下递推式:
n=1情况: f(n) =1
n>1情况: f(n) = 10f(n-1)+10^(n-1)
最前面可添加0-9 这十个数字,所以后面所有数字出现次数为 10f(n-1) ,加上最前面这个数字自己出现的次数10^(n-1)
f(2)=10*1+10^1=20
据此,可从高位向低位进行统计,再减去多余的0的个数即可。
10(10f(n-2)+10^(n-2))+10^(n-1) = 10^2*f(n-2)+2*10^(n-1) = 10^(n-1)*f(1) +(n-1)*10^(n-1) =n*10^(n-1)
bash 固定位置截取
${varible:start:len}:截取变量varible从位置start开始长度为len的子串。第一个字符的位置为0。