在 C++ 中寻找强大的能力 [重复]

Posted

技术标签:

【中文标题】在 C++ 中寻找强大的能力 [重复]【英文标题】:To Find Large Powers in C++ [duplicate] 【发布时间】:2013-11-17 04:38:47 【问题描述】:

我有两个数字 A 和 B

其中 A 和 B 的范围可以是 1

我们如何在 C++ 中找到 A^B 模数 M 的值??

【问题讨论】:

您需要使用任意精度的算术库。 Boost 和 OpenSSL 都有实现。如果您环顾四周,其他人也可以使用。 这里唯一重要的一点是 M 的边界是多少。M 可以放入 32/64 位整数吗?如果 M 是素数,则有一个简单的解决方案,对于所有其他 M 来说稍微复杂一点。 A和B可以写成p^q(p,q整数)吗?否则,您将需要任意精度库(您可能有 200,000 位数字......)。我在下面的答案中复制的技巧不起作用。 【参考方案1】:

在我指出的副本中,我特别喜欢的解决方案是https://***.com/a/8972838/1967396(参见那里的出处和参考资料)

为方便起见,我在此处复制代码(包装在 SCCE 中 - 但使用 C,而不是 C++):

#include <stdio.h>

int modular(int base, unsigned int exp, unsigned int mod)

    int x = 1;
    int i;
    int power = base % mod;

    for (i = 0; i < sizeof(int) * 8; i++) 
        int least_sig_bit = 0x00000001 & (exp >> i);
        if (least_sig_bit)
            x = (x * power) % mod;
        power = (power * power) % mod;
    

    return x;


int main(void) 
  printf("123^456mod567 = %d\n", modular(123, 456, 567));

太棒了,不是吗。

【讨论】:

这个问题中的数量明显大于你复制的那个。但是,是的,二进制取幂比简单的方法快很多。 @BenVoigt - 你是对的。 100^100000 是一个非常非常大的数字。基本原则不变,但需要更多思考才能获得正确的实现。【参考方案2】:

使用公式(a*b)mod m = (a*(b (mod m))) (mod m)。有关更多详细信息,请参阅 wiki 页面Modular exponentiation

【讨论】:

请注意,OP 想要做 (a^b)mod m,而不是 (a*b) mod m... 可能是您的拼写错误? 不不,这会(用 ^ 代替 *)神奇地降低复杂性(太不切实际了!)。它是:(a^b) = (aaa.....)。现在将使用公式。 @弗洛里斯 我现在明白你的意思了。你继续应用这个公式 B 次。事实上,使用(a (mod m ) * (b mod m) ) mod m,如果数字需要减少很多,您可以保持大小。一点动态编程意味着你不用做 B 次,而只做 O(log(B))。这很重要。【参考方案3】:

另一种解决方案假定您的 M 是固定的(或者至少您需要使用相同的 M 多次计算 A^B)。

第 1 步:计算 Euler's totient function(这需要对 M 进行因式分解,因此非常昂贵)。让我们拨打这个号码k

由于Fermat's little theorem,您的答案很简单:

(a % M)^(b % k)

现在,除非 M 是一个大素数,这大大简化了问题。

【讨论】:

+1 这确实是一个非常好的答案。它特别告诉您何时可以根据需要降低功率,例如考虑这个问题:查找:3^3^3 mod 1000000007 你能提供一个链接来理解这个结果的证明吗?【参考方案4】:

上面的问题可以使用下面的代码sn-p来解决。 因此,为确保此代码不会溢出,请检查 n * n

int modPow(int base, int exp, int n) 

base = base%n;

if (exp == 0)
    return 1;

else if (exp == 1)
    return base;

else if (exp%2 == 0)
    return modPow(base*base%n, exp/2, n);

else
    return base*modPow(base, exp-1, n)%n; 

【讨论】:

这不是尾递归,所以它肯定会导致问题中出现的数字的堆栈溢出(我假设从 int 更改为一些大整数库)

以上是关于在 C++ 中寻找强大的能力 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

使用 C++ 在 linux 中播放 .mp3 或其他音频文件 [重复]

如何使用 C++ 复制目录 [重复]

使用 C++ 查找文件中的所有重复模式

C++ fmt 格式动态重复参数

在 C++ 中按空格分割字符串的最快方法 [重复]

如何避免重复的工作?