比o(n)更快地计算a ^ n的模

时间:2018-12-27 16:44:18

标签: java c++ algorithm data-structures

我需要计算(a^n) mod b。我使用了此Java代码,但是当n太大时,它不够快。

for (long i = 0; i < n; i++) {
    ans = (ans * a) % b;
}

您可以在上面的代码中看到,n是一个long数字,因此该算法不够快。您是否建议任何更快的算法? 似乎是这个问题,但有一点不同:Fast way to calculate n! mod m where m is prime?

2 个答案:

答案 0 :(得分:7)

利用模块化算术的特性

(x × y) modulo b == ((x modulo b) × (y modulo b)) modulo b

使用上述乘法规则

(a^n) modulo b
= (a × a × a × a ... × a) modulo b 
= ((a modulo b) × (a modulo b) × (a modulo b) ... × (a modulo b)) modulo b

通过分治法计算结果。重复关系将为:

f(x, n) = 0                     if n == 0

f(x, n) = (f(x, n / 2))^2       if n is even
f(x, n) = (f(x, n / 2))^2 * x   if n is odd

这是C ++实现:

int powerUtil(int base, int exp, int mod) {
    if(exp == 0) return 1;
    int ret = powerUtil(base, exp / 2, mod) % mod;
    ret = 1LL * ret * ret % mod;
    if(exp & 1) {
        ret = 1LL * ret * base % mod;
    }
    return ret;
}

double power(int base, int exp, int mod) {
    if(exp < 0) {
        if(base == 0) return DBL_MAX; // undefined
        return 1 / (double) powerUtil(base, -exp, mod);
    }
    return powerUtil(base, exp, mod);
}

时间复杂度为O(logn)

Here is my original answer。希望对您有帮助!

答案 1 :(得分:-4)

您可以使用线程来除n。然后,当您最终确定mul时,您可以将最终结果进行mul,然后进行修改。

例如:

n = 4 然后分开2个线程,每个线程将执行以下操作:

int ans=1;
for(int i =0; i<n_thread;i++){
   ans = ans*a;
}

最后,当线程完成时,您必须将结果乘以mul,然后将其设为b。 我不会告诉您如何使用线程,因为您必须自己学习,但是如果您在搜索和了解线程后对线程有疑问,可以寻求帮助。