繁体   English   中英

C ++:如何计算升到大数的模数?

[英]C++ : How to calculate modulo of a number raised to large power?

我正在解决一个编程问题,我必须以答案mod 10 ^ 9 + 7的格式打印答案,其中“答案”是问题的实际答案。

我已经找到解决问题的算法,但是需要注意的是,问题的答案始终是格式m * 10 ^ n,其中

1 <= m <= 8和2 <= n <= 10 ^ 18,也就是说,答案10可以提高到10 ^ 18的幂。当然,直接计算10 ^ n可能会溢出。

接下来我该怎么办?

评估10^n mod M

您需要的是模幂 它可以计算log_2(b) (a^b)%m (对数为2)。

假设您需要计算10^9

  1. 一种方法是你依次多个109倍。
  2. 或者,使用分而治之的方法。

    10^9 = (10^8)*(10^1)

    10^8 = (10^4)*(10^4) :是否需要两次计算10^4

    10^4 = (10^2)*(10^2) :是否需要两次计算10^2

    10^2 = (10^1)*(10^1)

    10^1 = (10^1)*(10^0)

    10^0是基本情况。

    因此,我们基本上要做的是:

    1. 如果power是一个奇数,则我们计算base^(power-1)并将其乘以base得到base^power [ base^power = (base^(power-1)) * base) ]
    2. 如果power是偶数,则我们计算base^(power/2)并将其与自身相乘以获得base^power [ base^power = (base^(power/2)) * (base^(power/2)) ]。 但是我们只计算一次base^(power/2)

计算复杂度

如前所述这里

简要分析表明,这种算法使用floor(log_2(n))平方,最多使用floor(log_2(n))乘法。 更准确地说,乘法的数量比n的二进制展开式中存在的乘法数量少1。

因此,可以说运行时log_2(n) O(log_2(power))

评估模数部分:

很容易注意到,当计算一个最大为10^(10^18) ,我们必然会溢出甚至最大的原始类型( long long int )。 然后进入模乘 ,根据(a * b) % c = ((a % c) * (b % c)) % c 附带说明,当您直接查看代码时,您可能看不到该规则在使用中,但是如果您评估递归调用,则会使用该规则。

问题解决了?

我们通过计算运行中的模数来防止溢出。 假设,如果我们得到一些值为10^9值,则需要将其与自身相乘。 溢出? 不,这次不行。

ans = ((10^9 % 1000000007) * (10^9 % 1000000007)) % 1000000007
ans = 10^18 % 1000000007
ans = 49

码:

虽然有多种实现,但这是一个简单的实现:

const int M = 1e9 + 7;
long long int powxy(long long int x, long long int y) {
    if (y == 0) return 1;
    if (y%2 == 1) return (x*powxy(x, y-1))%M;
    long long int t = powxy(x, y/2);
    return (t*t)%M;
}

在这里测试。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM