快速幂(拓展移位运算,二进制的理解)

快速幂 - 图1快速幂 - 图2

分治的方法

  1. // 求:b^p
  2. // 思路:
  3. // 任意一个数p,可以表示成 p = 2 * p/2 + p%2
  4. // b^(2 * p/2 + p%2),就可以拆开后,递归调用f(p/2),递归终止边界是p == 0, return 1;
  1. // 求2^b
  2. #include <iostream>
  3. using namespace std;
  4. int f(int b)
  5. {
  6. if (b == 0) return 1;
  7. int t = f(b / 2);
  8. if (b & 1) return t * t * 2;
  9. else return t * t;
  10. }
  11. int main()
  12. {
  13. int a, b;
  14. cin >> b;
  15. cout << f(b) << '\n';
  16. return 0;
  17. }
  1. // 求a^b
  2. #include <iostream>
  3. using namespace std;
  4. typedef long long ll;
  5. int f(int a, int b)
  6. {
  7. if (b == 0) return 1;
  8. ll t = f(a, b / 2);
  9. if (b & 1) return t * t * a;
  10. else return t * t;
  11. }
  12. int main()
  13. {
  14. int a, b;
  15. cin >> a >> b;
  16. cout << f(a, b) << '\n';
  17. return 0;
  18. }

移位运算的方法

快速幂 - 图3
根据数学常识,每一个正整数可以唯一表示为若干个指数不重复的2的次幂的和。如果b在二进制下有k位,其中第i位的数字是快速幂 - 图4,那么
快速幂 - 图5
于是:
快速幂 - 图6
因为快速幂 - 图7向上取整,所以上式乘积项的数量不多于k个,
又因为
快速幂 - 图8
所以,通过k次递推求出每个乘积项,当快速幂 - 图9时,把该乘积项累积到答案中。
b & 1 运算可以取出 b 在二进制表示下的最低位, 而 b >> 1 运算可以舍去最低位,在递推的过程中将二者结合,就可以遍历 b 在二进制表示下的所有数字 快速幂 - 图10。时间复杂度是 快速幂 - 图11

  1. // 求 a^k mod p,时间复杂度 O(logk)
  2. // 模板请记忆
  3. // 写法1
  4. int qmi(int a, int k, int p)
  5. {
  6. int res = 1;
  7. while (k) //当k不是0的时候
  8. {
  9. if (k & 1) res = (LL)res * a % p;
  10. k >>= 1;
  11. a = (LL)a * a % p;
  12. }
  13. return res;
  14. }
  15. // 写法2
  16. int power(int a, int b, int p){
  17. int ret = 1;
  18. for (; b; b >>= 1){
  19. if (b & 1) ret = 1ll * ret * a % p;
  20. a = 1ll * a * a % p;
  21. }
  22. return ret;
  23. }
  1. //upd20220331
  2. int power(int a, int b, int p){
  3. int ret = 1;
  4. while (b){
  5. if (b & 1) ret = ret * a % p;
  6. b >>= 1;
  7. a = 1ll * a * a % p;
  8. }
  9. }
  10. // 洗牌
  11. // https://iai.sh.cn/problem/610
  12. // 结合倍增,ST表
  13. // f[N][30];是预处理出来的ST表
  14. int cur = i, b = k, t = 0;
  15. while (b){
  16. if (b & 1) cur = f[cur][t]; // 第二维,就是在枚举二进制位
  17. t++, b >>= 1;
  18. }

例题,取余运算(mod)

  1. 输入bpk的值,求 b^p mod k 的值。其中bpk为长整型数。

例题,2011

  1. 通过测试发现,2011n次方的结果,每500个数一循环。1次方、501次方、1001……结果一样。
  2. 2次方,502次方,1002次方……结果一样。所以,尽管指数可能有200位,只需要考虑最后的3位指数就可以了。如果指数n不足3位,直接计算2011n次方结果mod 10000就行了。