【问题标题】:Approach and Code for o(log n) solutiono(log n) 解决方案的方法和代码
【发布时间】:2017-07-18 19:36:09
【问题描述】:

f(N) = 0^0 + 1^1 + 2^2 + 3^3 + 4^4 + ... + N^N。

我想计算 (f(N) mod M)。

这些是约束。

  • 1≤N≤10^9
  • 1≤M≤10^3

这是我的代码

test=int(input())
ans = 0

for cases in range(test):
    arr=[int(x) for x in input().split()]
    N=arr[0]
    mod=arr[1]

    #ret=sum([int(y**y) for y in range(N+1)])
    #ans=ret

    for i in range(1,N+1):
        ans = (ans + pow(i,i,mod))%mod
    print (ans)

我尝试了另一种方法,但没有成功。 这是代码

from functools import reduce
test=int(input())
answer=0
for cases in range(test):
    arr=[int(x) for x in input().split()]
    N=arr[0]
    mod=arr[1]

    answer = reduce(lambda K,N: x+pow(N,N), range(1,N+1)) % M

    print(answer)

【问题讨论】:

  • pow(i,i,mod) 是做什么的?
  • 你要计算0^0 + 1^1 + ... + N^NM
  • @alfasin pow(x, y[, z]) 返回 x 的 y 次幂;如果 z 存在,则返回 x 的 y 次幂,以 z 为模(计算比 pow(x, y) % z 更有效)。两个参数的形式 pow(x, y) 等价于使用幂运算符:x**y。
  • 是的,@Patrick87。
  • 但这不是你描述你想要做的......在你写的问题中,你想要对所有0^0 + 1^1 + 2^2 + 3^3 + 4^4 + ... + N^N 求和,然后才计算模数(一次)。通过执行(ans + pow(i,i,mod))%mod,您将取模两次(这无关紧要,但仍然是多余的),这意味着您计算函数中每个项目的模

标签: algorithm time-complexity number-theory


【解决方案1】:

两个建议:

  1. 0^0 = 1 成为你所使用的。这似乎是我处理该问题的最佳指导。

  2. 通过乘以并取模来计算k^k

  3. 在执行任何其他操作之前,先将所有k(不是指数)更改为k mod M,然后执行初始传递。

  4. 在计算 (k mod M)^k 时,如果中间结果是您已经访问过的结果,您可以减少迭代次数以继续进行,但最多可以再增加一个循环。

    李>

示例:设 N = 5 和 M = 3。我们要计算 0^0 + 1^1 + 2^2 + 3^3 + 4^4 + 5^5 (mod 3)。

首先,我们应用建议 3。现在我们要计算 0^0 + 1^1 + 2^2 + 0^3 + 1^4 + 2^5 (mod 3)。

接下来,我们立即开始评估并使用建议 1 得到 1 + 1 + 2^2 + 0^3 + 1^4 + 2^5 (mod 3)。 2^2 是 4 = 1 (mod 3),我们记下它 (2^2 = 1 (mod 3))。接下来,我们发现 0^1 = 0, 0^2 = 0 所以我们有一个大小为 1 的循环,这意味着不需要进一步的乘法来告诉 0^3 = 0 (mod 3)。记下。 1^4 的类似过程(我们在第二次迭代中告诉我们有一个大小为 1 的循环,所以 1^4 是 1,我们注意到这一点)。最后,我们得到 2^1 = 2 (mod 3), 2^2 = 1(mod 3), 2^3 = 2(mod 3),一个长度为 2 的循环,所以我们可以向前跳过一个耗尽的偶数2^5,无需再次检查,我们知道 2^5 = 2 (mod 3)。

我们的总和现在是 1 + 1 + 1 + 0 + 1 + 2 (mod 3) = 2 + 1 + 0 + 1 + 2 (mod 3) = 0 + 0 + 1 + 2 (mod 3) = 0 + 1 + 2 (mod 3) = 1 + 2 (mod 3) = 0 (mod 3)。

这些规则将对您有所帮助,因为您的案例看到 N 比 M 大得多。如果反过来 - 如果 N 远小于 M - 您将不会从我的方法中获得任何好处(并且取模 w.r.t. M 会对结果的影响较小)。

伪代码:

Compute(N, M)
1. sum = 0
2. for i = 0 to N do
3.    term = SelfPower(i, M)
4.    sum = (sum + term) % M
5. return sum

SelfPower(k, M)
1. selfPower = 1
2. iterations = new HashTable
3. for i = 1 to k do
4.    selfPower = (selfPower * (k % M)) % M
5.    if iterations[selfPower] is defined
6.        i = k - (k - i) % (i - iterations[selfPower])
7.        clear out iterations
8.    else iterations[selfPower] = i
9. return selfPower

示例执行:

resul = Compute(5, 3)
    sum = 0
    i = 0
        term = SelfPower(0, 3)
            selfPower = 1
            iterations = []
            // does not enter loop
            return 1
        sum = (0 + 1) % 3 = 1
    i = 1
        term = SelfPower(1, 3)
            selfPower = 1
            iterations = []
            i = 1
                selfPower = (1 * 1 % 3) % 3 = 1
                iterations[1] is not defined
                    iterations[1] = 1
            return 1
        sum = (1 + 1) % 3 = 2
    i = 2
        term = SelfPower(2, 3)
            selfPower = 1
            iterations = []
            i = 1
                selfPower = (1 * 2 % 3) % 3 = 2
                iterations[2] is not defined
                    iterations[2] = 1
            i = 2
                selfPower = (2 * 2 % 3) % 3 = 1
                iterations[1] is not defined
                    iterations[1] = 2
            return 1
        sum = (2 + 1) % 3 = 0
    i = 3
        term = SelfPower(3, 3)
            selfPower = 1
            iterations = []
            i = 1
                selfPower = (1 * 3 % 0) % 3 = 0
                iterations[0] is not defined
                    iterations[0] = 1
            i = 2
                selfPower = (0 * 3 % 0) % 3 = 0
                iterations[0] is defined as 1
                    i = 3 - (3 - 2) % (2 - 1) = 3
                    iterations is blank
            return 0
        sum = (0 + 0) % 3 = 0
    i = 4
        term = SelfPower(4, 3)
            selfPower = 1
            iterations = []
            i = 1
                selfPower = (1 * 4 % 3) % 3 = 1
                iterations[1] is not defined
                    iterations[1] = 1
            i = 2
                selfPower = (1 * 4 % 3) % 3 = 1
                iterations[1] is defined as 1
                    i = 4 - (4 - 2) % (2 - 1) = 4
                    iterations is blank
            return 1
        sum = (0 + 1) % 3 = 1
    i = 5
        term = SelfPower(5, 3)
            selfPower = 1
            iterations = []
            i = 1
                selfPower = (1 * 5 % 3) % 3 = 2
                iterations[2] is not defined
                    iterations[2] = 1
            i = 2
                selfPower = (2 * 5 % 3) % 3 = 1
                iterations[1] is not defined
                    iterations[1] = 2
            i = 3
                selfPower = (1 * 5 % 3) % 3 = 2
                iterations[2] is defined as 1
                    i = 5 - (5 - 3) % (3 - 1) = 5
                    iterations is blank
            return 2
        sum = (1 + 2) % 3 = 0
    return 0

【讨论】:

  • 在最坏的情况下,M 是素数,并且在计算 M 项之前,您不会遇到“循环”(然后通过鸽洞原理保证您会遇到一个)。尽管如此,如果N >> M,这仍然是一个公平的成本节约。另一个节省是在N >> M 的情况下智能地分解出类似的碱基,并与类似的碱基共享中间结果。同样,如果M >> N,则不可能有任何重要的技巧,因为这会转移到与模数无关的极限。
  • 谢谢。我会实施你的方法。
【解决方案2】:

为什么不使用简单的递归来求幂的递归和

def find_powersum(s):
    if s == 1 or s== 0:
        return 1
    else:
       return s*s + find_powersum(s-1)  

def find_mod (s, m):   
   print(find_powersum(s) % m)

find_mod(4, 4)
2

【讨论】:

  • 简单递归将给出 TLE。 1
  • @Akashdeep Jassal 您正在使用哪个 IDE 或编译器
  • m 不一定等于n
猜你喜欢
  • 1970-01-01
  • 2017-11-19
  • 2019-09-13
  • 2016-03-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-11
  • 2021-04-20
相关资源
最近更新 更多