如果你对 pow(2,3)的理解还停留在3个2相乘,那就太low了,其实对幂运算还有一种更快,更简洁的算法——快速幂。
其实快速幂的本质原理非常简单,我们已知 24求28,不就是 24 * 24嘛,快速幂就是这个原理。
那么现在你可能会问,如果是奇数次幂该怎么办?
29就可以用 2 * 28来计算嘛。
所以总结如下:
- 当b是奇数时,那么有 a^b = a * a^*(b-1)
- 当b是偶数时,那么有 a^b = a^(b/2) * a^(b/2)
const int mod = 1e9 + 9;
long long qpow(long long x, long long y)
{
long long ret = 1;
x = x % mod;
while (y)
{
if (y % 2 == 1) //如果为奇数次幂
ret = (ret * x) % mod;
y /= 2;
x = (x * x) % mod;
}
return ret % mod;
}
但是这样算依然不够快,我们要知道—— “/”运算需要40个CPU时钟;“*”运算需要4个CPU时钟;“+-”一般需要2个CPU时钟,但是,位运算只要1个!
为了提高快速幂的效率和速度,我们可以将 y % 2 == 1 改为 y & 1;将 y /= 2 改为 y >>= 1 (y右移移位并赋值)。
const int mod = 1e9 + 9;
long long qpow(long long x, long long y)
{
long long ret = 1;
x = x % mod;
while (y)
{
if (y & 1) // y % 2 == 1
ret = (ret * x) % mod;
y >>= 1; // y /= 2
x = (x * x) % mod;
}
return ret % mod;
}
下面给大家介绍一下简单的移位运算:
1.右移运算符(>>)
例如:11的二进制形式为:1011,然后把低位的最后两个数字移出,因为该数字是正数,所以在高位补零。则得到的最终结果是 0010。转换为十进制是 2。所以代码中 y >>= 1 的意思就是将二进制 y 右移移位并赋值,二进制下右移移位就是除以 2。
2. 按位与运算符(&)
按位与运算符"&"是双目运算符。 其功能是参与运算的两数各对应的二进位相与。只有对应的两个二进位均为1时,结果位才为1 ,否则为0。参与运算的数以补码方式出现。
例如:9&5 可写算式如下: 1001 & 0101 为 0001 ,可见 9&5=1。