Python中的模块化算法

时间:2013-03-17 23:15:24

标签: python list-comprehension modular-arithmetic

问题48来自Project Euler的描述:

  

系列,1 ^ 1 + 2 ^ 2 + 3 ^ 3 + ... + 10 ^ 10 = 10405071317.找到最后一个   系列的十位数,1 ^ 1 + 2 ^ 2 + 3 ^ 3 + ... + 1000 ^ 1000。

我刚刚在Python中使用单行解决了这个问题:

print sum([i**i for i in range(1,1001)])%(10**10)

我几乎立即就这样做了,因为我记得在Python中分裂模型非常快。但我仍然不明白这是如何工作的(Python做了哪些优化?)以及为什么如此快。

你可以向我解释一下吗? mod 10**10操作是否被优化为应用于列表推导的每次迭代而不是整个总和?

$ time python pe48.py 
9110846700

real 0m0.070s
user 0m0.047s
sys  0m0.015s

2 个答案:

答案 0 :(得分:4)

鉴于此

print sum([i**i for i in range(1,1001)])%(10**10)

print sum([i**i for i in range(1,1001)])

在Python中的功能同样快,你上一个问题的答案是'不'。

因此,Python必须能够非常快速地进行整数取幂。并且整数取幂是O(log(n))乘法:http://en.wikipedia.org/wiki/Exponentiation#Efficient_computation_of_integer_powers

基本上做的是,而不是做2 ^ 100 = 2 * 2 * 2 * 2 * 2 ... 100次,你意识到2 ^ 100也是2 ^ 64 * 2 ^ 32 * 2 ^ 4 ,你可以一遍又一遍地得到2 ^ 2然后2 ^ 4然后2 ^ 8 ......等等,一旦你找到了所有这三个组件的值,你就将它们相乘得出最终答案。这需要更少的乘法运算。如何解决它的具体细节有点复杂,但Python已经足够成熟,可以在这样的核心功能上进行优化。

答案 1 :(得分:1)

不,它适用于整个总和。总和本身计算速度非常快。如果参数是整数,那么做指数就不那么难了。