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

时间:2018-04-07 14:59:31

标签: c++ algorithm number-theory mod

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

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

1 <= m <= 8且2 <= n <= 10 ^ 18,即在答案10中可以将其提升到大到10 ^ 18的幂。当然,直接计算10 ^ n可能会溢出。

接下来我该怎么做?

1 个答案:

答案 0 :(得分:2)

评估10^n mod M

您需要的是Modular Exponentiation。它可以在(a^b)%m(日志库2)中计算log_2(b)

示例

我们假设您需要计算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)一次。
  3. 计算复杂性

    如上所述here

      

    简要分析表明,这种算法使用floor(log_2(n))方形和   最多floor(log_2(n))次乘法。更准确地说,   乘法次数比存在的次数少一次   在n。

    的二进制扩展中

    因此,我们可以说运行时的顺序为log_2(n)。 (O(log_2(power))

    评估模数部分:

    很容易注意到,在计算与10^(10^18)一样大的值时,我们必然会溢出最大的基本类型(long long int)。在这里输入Modular Multiplication,根据(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;
    }
    

    经过测试here