Sum

时间:2018-07-02 18:23:08

标签: python python-3.x performance optimization

我正在查看Codechef中的实践问题,我发现了这个问题。我是Python新手。我已经使用Python3编写了以下代码。我不断收到“ 超出时间限制”错误。寻找代码的一些优化。

问题陈述如下:

给出n和m,计算1 ^ 1 + 2 ^ 2 + 3 ^ 3 + ... + n ^ n模m。

输入: 第一行包含1≤t≤10(测试用例的数量)。然后是测试用例定义。每个测试用例的形式为:1≤n 1018,1≤m≤200000

示例

Input:
6
1 100000
2 100000
3 100000
4 100000
5 100000
6 100000

Output:
1
5
32
288
3413
50069

这是我的代码:

t = int(input())
for j in range (1,t+1):
    ans = 0
    n, m = [int(x) for x in input().split()]
    for i in range (1,n+1):
        ans = (ans + pow(i,i))%m
    print (ans)

谢谢。

2 个答案:

答案 0 :(得分:0)

O(m log n)中的解决方案:

def geometric(n,b,m):
    T=1
    e=b%m
    total = 0
    while n>0:
        if n&1==1:
            total = (e*total + T)%m
        T = ((e+1)*T)%m
        e = (e*e)%m
        n = n//2
    return total

def efficient_solve(n, m):
    ans = 0
    for x in range(1, min(n, m) + 1):
        k = pow(x, m, m)
        s = pow(x, x, m)

        times = (n // m) + (x <= n % m)

        ans += s * geometric(times, k, m)
        ans = ans % m
    return ans  

geometric计算取自https://stackoverflow.com/a/42033401/3308055

的模的几何级数m

说明

N太大,我们需要一种在一次操作中计算多个和结果的方法。

请注意,x ^ x % m = (mk + i) ^ (mk + i) % m的i

(mk + i) ^ (mk + i) % m = (mk + i) * (mk + i) * (mk + i) * ... * (mk + i)(mk + i)次

如果我们开始进行分配,则几乎所有结果将至少具有1 mk作为因子,而mk * whatever % m将为0。

唯一没有mk因子的结果将是i * i * i * i * ... * i(mk + i)倍。即i^(mk + i)

因此,如果n = 5且m = 3,我们可以求解1^1 + 2^2 + 3^3 + 4^4 + 5^5 % 3而不是求解1 ^ (0 + 1) + 2 ^ (0 + 2) + 0 ^ (3 + 0) + 1 ^ (3 + 1) + 2 ^ (3 + 2) % m

这很好,但是我们仍然需要执行O(n)运算。让我们尝试将其中一些总和进行分组。我们将基于i % m进行分组,共有3个分组:

  • 1 ^ (0 + 1) + 1 ^ (3 + 1)
  • 2 ^ (0 + 2) + 2 ^ (3 + 2)
  • 0 ^ (3 + 0)

我们如何有效地计算每个小组的结果? 注意,对于每个组,我们都有相同的底数,并且每个和的指数增加m。如果我们知道第一个和(1 ^ (0 + 1))的结果,那么下一个和(1 ^ (3 + 1))相对于%m会如何变化?

1 ^ (3 + 1) % m = (1 ^ 1 % m) * (1 ^ 3 % m) % m。如果n更高,并且我们在这个组中有1 ^ (6 + 1),则为1 ^ (6 + 1) % m = (1 ^ 1 % m) * (1 ^ 3 % m) * (1 ^ 3 % m) % m。请注意,对于同一组中的每个随后的总和,我们只需要添加(1 ^ 3 % m)的结果。一般来说,我们需要添加base ^ m % m

我们每个小组有多少笔款项?好吧,每n times = (n // m) + (x <= n % m)。

我们将x称为组的索引,该索引也将成为指数的基础。我们将有min(n,m)个组

我们致电k的结果x ^ m % m。让我们将s的结果称为x ^ x % m

求解该组所有和的结果将是:

s + s * k + s * k^2 + s * k^3 ... + s * k^(times - 1)

这等效于:

s * (1 + k + k^2 + k^3 ... + k^(times - 1))

这里有一个几何级数,可以高效地进行计算。这样,我们就有了计算问题答案所需的一切。

答案 1 :(得分:0)

numpy解决方案

import numpy as np

n = 6
m = 100000
arange = np.arange(1, n+1)
power = np.power(arange, arange)
result = np.cumsum(power) % m