系列之和:1 ^ 1 + 2 ^ 2 + 3 ^ 3 + ... + n ^ n(mod m)

8 algorithm series

有人能给我一个关于大n(比如10 ^ 10)的有效算法的想法来找到上述系列的总和吗?

我的代码在n = 100000和m = 200000时被克隆

#include<stdio.h>

int main() {
    int n,m,i,j,sum,t;
    scanf("%d%d",&n,&m);
    sum=0;
    for(i=1;i<=n;i++) {
        t=1;
        for(j=1;j<=i;j++)
            t=((long long)t*i)%m;
        sum=(sum+t)%m;
    }
    printf("%d\n",sum);

}
Run Code Online (Sandbox Code Playgroud)

Meh*_*ari 24

两个笔记:

(a + b + c) % m
Run Code Online (Sandbox Code Playgroud)

相当于

(a % m + b % m + c % m) % m 
Run Code Online (Sandbox Code Playgroud)

(a * b * c) % m
Run Code Online (Sandbox Code Playgroud)

相当于

((a % m) * (b % m) * (c % m)) % m
Run Code Online (Sandbox Code Playgroud)

因此,您可以使用O(log p)中的递归函数计算每个项:

int expmod(int n, int p, int m) {
   if (p == 0) return 1;
   int nm = n % m;
   long long r = expmod(nm, p / 2, m);
   r = (r * r) % m;
   if (p % 2 == 0) return r;
   return (r * nm) % m;
}
Run Code Online (Sandbox Code Playgroud)

并使用for循环求和元素:

long long r = 0;
for (int i = 1; i <= n; ++i)
    r = (r + expmod(i, i, m)) % m;
Run Code Online (Sandbox Code Playgroud)

该算法为O(n log n).

  • @rahul:你的内部j循环在O(i)中运行.Mehrdad的函数在O(log i)中运行.通过调用Mehrdad的功能来替换你的内循环,你将获得一个很大的加速. (4认同)
  • 我相信你在这些方程式中还需要一个'mod':'(a%m + b%m + c%m)%m'和'(a%m)*(b%m)*(c%m) %m'. (3认同)

小智 5

我认为你可以使用欧拉定理来避免一些指数,因为phi(200000)= 80000.中国剩余定理也可能有所帮助,因为它减少了模数.

  • 您只需要计算一次phi.欧拉定理说,如果(a,b)= 1,则a ^ phi(b)= 1 mod b.然后你可以将^ c mod b简化为形式a ^ c'mod b,其中c'<phi(b). (2认同)
  • 提示 - 尝试编辑您的答案。精心制作的。描述并解释您建议的算法。尝试发布一些代码。链接到维基百科。另外,中国剩余定理不是用于一组方程吗? (2认同)
  • 欧拉定理和中国提醒定理很容易查找,它们(在这里)完全相关 - 使用欧拉定理来计算m中每个主要幂的和mod,并使用CRT将它们组合在一起. (2认同)