将数字提高到巨大的指数

时间:2018-09-11 20:03:26

标签: c++ arrays algorithm math integer-arithmetic

给我数字3和一个变量'n',该变量可以高达1000000000000(十亿)。我必须打印3^n modulo 100003的答案。我尝试了以下方法:

  1. 我尝试使用函数std::pow(3,n),但不适用于大指数(在处理过程中无法应用模数)。
  2. 我尝试实现自己的函数,该函数会将数字3乘幂n,以便我可以在需要时应用模,但是当测试非常大的数字时,这种方法被证明太慢了。
  3. 最后,我尝试对数字'n'进行素分解,然后使用'n'因子(及其出现的次数)来建立答案,这似乎是我可能会想到的最好方法(如果正确的话)。问题是我要对已经是质数很大的数字做什么?

    这些就是我的想法,如果有人认为有更好的方法(或者我的方法之一是最佳方法),我将不胜感激。

2 个答案:

答案 0 :(得分:8)

利用模块化算术的特性

(a × b) modulo M == ((a module M) × (b modulo M)) modulo M

使用上述乘法规则

(a^n) modulo M 
= (a × a × a × a ... × a) modulo M 
= ((a module M) × (a modulo M) × (a modulo M) ... × (a modulo M)) modulo M

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

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);
}

答案 1 :(得分:2)

这是为了扩大Kaidul的答案。

100003是质数,它立即转换为Fermat's Little Theorem:升为质数幂的任何数字本身都与该质数取模。这意味着您不需要提高第n的力量。 n % 100002次幂即可。

编辑:示例。

说,n是200008,即100002 * 2 + 6。现在,

3 ^ 200007 =
3 ^ (100002 + 100002 + 6) = 
3 ^ 100002 * 3 ^ 100002 * 3 ^ 6

FLT声称(3 ^ 100002) % 100003 == 1和上面的最后一行以100003为模,减少为3 ^ 6。通常,对于素数p

(k ^ n) % p == k ^ (n % p)

当然,只有指数n大于p时,它才会加快计算速度。根据您的请求(指数100,模100003),没有什么可减少的。直接使用Kaidul的方法。