【问题标题】:Raising a number to a huge exponent将数字提高到一个巨大的指数
【发布时间】:2019-02-16 09:39:42
【问题描述】:

我得到数字 3 和一个变量“n”,它可以高达 1 000 000 000(十亿)。我必须打印3^n modulo 100003 的答案。我尝试了以下方法:

  1. 我尝试使用函数std::pow(3,n),但它不适用于大指数(在此过程中无法应用模数)。
  2. 我尝试实现自己的函数,将数字 3 提高到 n 次方,以便在需要时应用模数,但在测试非常大的数字时,这种方法被证明太慢了。
  3. 最后,我尝试对数字“n”进行素数分解,然后使用“n”的因数(以及它们出现的次数)来构建答案,这似乎是我能想到的最佳方法(如果它是正确的)。问题是对于一个已经是素数的巨大数字我该怎么办?

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

【问题讨论】:

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


【解决方案1】:

利用模运算的性质

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

【讨论】:

  • @Kaidul 非常感谢。
【解决方案2】:

这是为了补充 Kaidul 的答案。

100003 是一个素数,它立即转换为Fermat's Little Theorem:任何提升到素数幂的数都与它本身模数一致。这意味着您不需要提高到n'th 次方。 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)

当然,只有当指数@​​987654332@ 大于p 时,它才会加快计算速度。根据您的要求(指数100,模100003),没有什么可以减少的。直接进入 Kaidul 的方法。

【讨论】:

  • 我似乎不明白如何准确地使用该定理。你能解决一个例子,让我更清楚吗?例如,假设我们有底数为 3,指数为 100,模数为 100003。结果是 60258,那么我如何使用这个定理得到正确的答案?
  • 知道了。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-02
  • 1970-01-01
  • 1970-01-01
  • 2012-06-22
  • 1970-01-01
相关资源
最近更新 更多