为什么我们不需要对Fast Power算法中的每个操作数执行模运算?

时间:2016-10-17 04:02:40

标签: c++ math modular-arithmetic

今天我练习了一个谜题"快速动力",它使用了一个公式: (a * b) % p = (a % p * b % p) % p计算(a^n)%p,类似:2^31 % 3 = 2

然而,当我发现答案使用((temp * temp) % b * a) % b;来解决n是奇数的情况时,我很困惑,例如2^3

(temp (temp * temp) % b * a递归或(temp * temp) % b)。

不应该是((temp * temp) % b * a%b) % b吗?

因为根据这个公式,一切都应该%b在一起。

1 个答案:

答案 0 :(得分:2)

  

不应该是((temp * temp) % b * a % b) % b吗?

没有。对于a,如果事先知道a不会溢出(a小于b),则不必修改它。

这个想法是modular arithmetic适用于加法和乘法。 通常会执行(a + b) % M = (a % M + b % M) % M(a * b) % M = (a % M * b % M) % M之类的操作,以避免(a * b)(a + b)溢出,并将值保持在一定范围内。

示例:

const int Mod = 7;
int a = 13;
int b = 12;
int b = b % Mod; // b now contains 5 which is certainly smaller than Mod

int x = (a % Mod * b) % Mod; // you won't need to mod b again if you know beforehand b is smaller than Mod

更新

电源功能的C ++实现:

#define MOD 1000000007
// assuming x and n both be positive and initially smaller than Mod
int power(int x, int n) {
    if(n == 0) return x;
    int half = power(x, n / 2) % Mod;
    int ret = (half * half) % Mod; // you didn't need to do (half % Mod * half % Mod) % Mod because you already know half is smaller than Mod and won't overflow. 
                                   // Modulas being performed on the multiplied output, so now ret will be smaller than Mod
    if(n & 1) {
        ret = (ret * x) % Mod; // you didn't need to do (ret % Mod * x % Mod) % Mod
                               // because you already know ret and x is smaller than Mod
    }
    return ret;
}

Mod是一项昂贵的操作。所以你应该尽可能避免它。