我该如何优化此代码?

时间:2017-11-18 21:07:10

标签: python algorithm optimization

def f(n):
    Total_Triangles = 0
    for i in range(1,n+1):
        term = 3**(i-1)
        Total_Triangles+=term
    return Total_Triangles
Q = int(input())
for i in range(Q):
    n = int(input())
    Ans = f(n)*4 +1
    print(Ans%1000000007)

如何处理此代码中的时间限制错误?

2 个答案:

答案 0 :(得分:2)

Karan有一个很好的答案。它会加快你原来的方法,但你仍然最终计算出巨大的数字。幸运的是,Python的Long类型可以做到这一点,但我希望它不像本机32位或64位整数类型那样高效。

你被告知给出一个巨大数字M,1,000,000,007的答案。您可以在整个过程中使用modular arithmetic来改进算法,这样您的数字就不会变得非常大。在模运算中,这是真的:

(a + b) % M == (a % M + b % M) % M
(a * b) % M == (a % M * b % M) % M

一种方法可能是使用模运算预先计算所有可能的Q值:

M = 1000000007

def makef(m):
    """Generator to create all sum(3**i) mod M"""

    n = 1
    s = 0

    for i in range(m):
        yield s

        s = (s + n) % M
        n = ((n  + n) % M + n) % M

f = list(makef(100000))
Q = int(input())

for i in range(Q):
    n = int(input())
    print (f[n] * 4 + 1) % M

这将在一个大循环中进行计算,但只进行一次,并且应该足够快以满足您的要求。

Python为您提供了第二种方式:表达式a ** b映射到内置函数pow(a, b)。此函数可以采用第三个参数:模块化算术的基础,以便pow(a, b, M)计算(a ** b) % M而不会产生巨大的中间结果。

现在你可以使用Karan的整洁配方。但等等,有一个陷阱:你必须将权力的结果除以2。上面的模块化关系不适用于除法。例如,(12 // 2) % M为6,但如果您首先应用模运算符,正如pow函数所做的那样,您将获得((12 % 2) // 2) % M,这是1而不是您想要的。一种解决方案是计算功率模2 * M,然后除以2:

def f(n):
    return pow(3, n, 2 * 1000000007) // 2

Q = int(input())
for i in range(Q):
    n = int(input())
    print (f(n) * 4 + 1) % M

(注意3的所有幂都是奇数,所以我删除了- 1并让整数除法完成工作。)

旁注:选择M的值,以便添加两个小于M的数字符合带符号的32位整数。这意味着C,C ++或Java的用户不必使用bignum库。但请注意,3 * n仍然可以溢出已签名的int,因此在乘以3时必须小心:改为使用((n + n) % M + n) % M

答案 1 :(得分:1)

您想要找到3 ** 0 + 3 ** 1 ... + 3 ** (n - 1),这只是一个几何系列,包含第一项a = 1,公共比率r = 3和条件数n = n,并使用一个几何系列公式,我们可以更快地找到f(n),如下所示:

def f(n):
    return (3 ** n - 1) // 2