求1到n的所有正整数中1出现的次数

来源:互联网 发布:gpt转mbr数据会丢失吗 编辑:程序博客网 时间:2024/04/30 02:22

分析

设n的位数为L。1到n的所有整数中1的个数由以下(1)(2)两部分构成

(1)长度小于L的所有正整数中的1

           包含i个1的数有 C(i, L-1)*9^(L-1-i)个,其中包含0个1的情况中有这个数字是0的情况,不过不影响对1的计数。故长度小于L的所有正整数中1的个数为C(i, L-1)*9^(L-1-i)*i

(2)长度为L且小于n的所有正整数中的1

          从最高位开始,将n的每一位计算出来设为 a1, a2, ..., aL, 前n位包含1的个数为count[n]

          从前往后处理每一位

          sum=0;          Loop:          A:m位为0,该位置不能改变,继续处理下一位,下一位的计数包含了这种情况          B:m位大于0            B1:m位为1,则令m位为0,后面的位任意取数,1的个数为 sum{i=0~L-m}{C(i, L-m)*9^(L-m-i)*(i+count[m])}            B2:m位大于1               B2A:m位取1,一的个数为sum{i=0~L-m}{C(i, L-m)*9^(L-m-i)*(1+i+count[m])}               B2B:m位不取1,1的个数为 (am-1)*B1          将对应情况的计数累加到sum上          循环。
将(1)(2)两部分的计数相加。

改进

考虑到各位上的循环现象,有更简单的方法

# -*- coding: cp936 -*-import timedef getNumberOfDigits(n):    res = 0    base = 10;    # 从最低位到最高位,分别计算所有数字在该位上出现1的次数,累加到res上    while(10*n/base != 0):        # 当前位每一个完整循环中,1出现的次数        a = n/base        # 当前位完整循环的次数        b = base/10        # 加上当前位完整循环中1出现的次数        res += b*a        # 计算当前为剩下的没有循环完整的数列中的1的个数        if(n%base >= 2*b):            # 虽然没有循环完,但当前循环中所有1已经出现完了            res += b        else:            # 当前循环只出现了部分1            res += n%base-b+1        base *= 10    return resdef test(n):    time1= time.clock()    res = getNumberOfDigits(n)    time2= time.clock()    print n, "\t", res, "\t", (time2-time1)*1000, "ms"  # 测试for i in range(1, 30):    test(i)    test(987654)test(9876543)test(98765432)test(987654321)

输出为

1 1 0.00434199442804 ms2 1 0.00355254089567 ms3 1 0.00315781412948 ms4 1 0.0197363383092 ms5 1 0.00355254089567 ms6 1 0.00986816915463 ms7 1 0.00394726766184 ms8 1 0.00394726766184 ms9 1 0.00355254089568 ms10 2 0.0201310650754 ms11 4 0.00513144796038 ms12 5 0.00473672119422 ms13 6 0.0276308736329 ms14 7 0.0248677862696 ms15 8 0.0055261747266 ms16 9 0.0236836059711 ms17 10 0.004341994428 ms18 11 0.0189468847769 ms19 12 0.025657239802 ms20 12 0.0224994256726 ms21 13 0.0118418029855 ms22 13 0.0244730595035 ms23 13 0.004341994428 ms24 13 0.00473672119417 ms25 13 0.00434199442811 ms26 13 0.004341994428 ms27 13 0.0256572398021 ms28 13 0.00394726766184 ms29 13 0.00473672119428 ms987654 595336 0.0232888792049 ms9876543 6941015 0.00868398885601 ms98765432 79286694 0.0205257918416 ms987654321 891632373 0.0374990427876 ms


原创粉丝点击