Python入门习题(98)——OpenJudge百练习题:求10000以内n的阶乘

OpenJudge百练第2731号习题:求10000以内n的阶乘

题目描述

来源
OpenJudge网站 —— 百练习题集-第2731号习题

要求
总时间限制: 5000ms 内存限制: 655360kB

描述

求10000以内n的阶乘。

输入
只有一行输入,整数n(0<=n<=10000)。
输出
一行,即n!的值。
样例输入
100
样例输出

93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000

来源
JP06

解题思路

  1. 这一题的难点是:n很大时,n!的结果会大到无法用一个整数变量来存储。解决办法是用一个列表(即数组)来存储作为结果的整数的各个数位。

  2. 下面一节给出的代码中,用n_digits列表存储作为结果的整数的各个数位。n_digits[0]是个位,[1]是十位,[2]是百位, …,依次类推。

  3. 假设n_digits存储了(m-1)!的结果,那么如何求m!呢?答案是,n_digits的各个数位分别乘以m。具体做法是:
    (1)令jinwei = 0。jinwei变量记住向前的进位。
    (2)个位乘以m。n_digits[0] = n_digits[0] * m + jinwei。进位jinwei = n_digits[0]除以10的商;新的个位n_digits[0] = n_digits[0]除以10的余数。
    (3)十位乘以m,加上进位jinwei。n_digits[1] = n_digits[1] * m + jinwei。进位jinwei = n_digits[1]除以10的商;新的个位n_digits[1] = n_digits[1]除以10的余数。
    (4)百位乘以m,加上进位jinwei。n_digits[2] = n_digits[2] * m + jinwei。进位jinwei = n_digits[2]除以10的商;新的个位n_digits[2] = n_digits[2]除以10的余数。
    (5)…
    (6)依次类推,一直到(m-1)!的最高位。把最高位的进位记作jinwei。
    (7)如果jinwei > 0,那么增设一位最高位,其值 = jinwei % 10。令jinwei = jinwei 除以10的商。
    (8)如果jinwei > 0,那么增设一位最高位,其值 = jinwei % 10。令jinwei = jinwei 除以10的商。
    (9)…
    (10)重复上一步骤,直至jinwei等于0。

参考答案

# print("10!=", 10*9*8*7*6*5*4*3*2*1)
# print("15!=", 15*14*13*12*11*10*9*8*7*6*5*4*3*2*1)
from array import array
n_digits = array('L')  #n_digits[0]是个位,[1]是十位,[2]是百位, ...

#n_digits存储了(m-1)!的结果,求出m!的结果
def times(n_digits, m):
    #各个数位乘以m
    jinwei = 0
    for i in range(len(n_digits)):
        n_digits[i] = n_digits[i] * m + jinwei
        jinwei = n_digits[i] // 10
        n_digits[i] = n_digits[i] % 10
    #最高位的进位目前可能是数十,数百,数千,...
    while jinwei > 0:
        n_digits.append(jinwei % 10)
        jinwei = jinwei // 10
    return n_digits

n = int(input())

if n <= 1:
    print(1)
else:
    n_digits.append(1) #1! = 1
    for i in range(2, n+1):
        n_digits = times(n_digits, i)
    for d in n_digits[len(n_digits)-1::-1]:
        print(d, end='')
    print()

测试用例

  1. 题目描述给出的测试用例,结果值比较大。要比对样例输出和程序输出,可以把两组数据复制到同一个编辑器窗口内,上下对齐,比对就容易了。

  2. 小一点的n。
    样例输入
    10
    样例输出
    3628800

  3. 另一个小一点的n。
    样例输入
    15
    样例输出
    1307674368000
    你应该能够猜到上一节代码中的前两行的作用了。

  4. n=1。
    样例输入
    1
    样例输出
    1

小结

  1. 把“参考答案”一节的代码提交到OpenJudge网站上后,反馈的结果是“ Time Limit Exceeded ”,意思是超时,用时超过了50000ms(即50秒)。采用同样的算法,用C语言实现的代码提交到OpenJudge网站上后,返回的结果是“Accepted”,用时2373ms。可见:(1)算法没有问题。(2)Python的运行效率比较低。
  2. 有人把类似问题概括为高精度整数类型的问题。这一类问题通常会生成一个巨大的数,大到无法用变量直接存储的数。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章