快速幂

快速幂就是快速求解一个整数a的n次幂的算法,传统的求解思路是按照线性的求解顺序:\(a^n = a*a*a*...*a\),这样做的算法时间复杂度是\(O(n)\),而快速幂借助二进制的思想,可以将时间复杂度降低到\(O(logn)\)

int quick_pow(int a, int n)
{
    int ans = 1;
    int tot = a;
    while(n){
        if(n&1) ans*=tot; // 如果这位上为1,那么ans就乘以当前的tot
        tot*=tot; // tot自乘
        n>>=1; // 相当于n/2
    }
}

快速幂的算法很简单,也很好理解;

就是把n看成二进制的数,比如对于\(a^{11}\)\((11)_{10} = (1011)_2\),那么使用快速幂的求解过程如下:

  1. \(ans=a, tot = a^2, n=(101)_2\)
  2. \(ans=a^3, tot=a^4, n=(10)_2\)
  3. \(ans=a^3, tot=a^8, n=(1)_2\)
  4. \(ans=a^11, tot=a^{16}, n=0\)

这里本质上是使用二进制表示n的思想,因为任意一个十进制的整数都可以表示成二进制的数

时间复杂度由于tot是指数上升的,所以乘法的次数是\(logn\)


例题:洛谷p1226

ac代码:

#include<bits/stdc++.h>
typedef long long ll; // 要使用ll类型
using namespace std;
int q_pow(ll a, ll n, ll k)
{
   ll ans = 1;
   ll tot = a;
   while(n){
   	if(n&1) ans = (ans*tot)%k;
   	tot = (tot*tot)%k; // 这里也要取余,but why? 
   	n>>=1;
   }
   return ans%k; // 输出答案的时候不要忘记把最终的答案再对p取一次模,否则就会只有 84分。
} 

int main()
{
	ll b, p, k;
	cin >> b >> p >> k;
	printf("%lld^%lld mod %lld=%lld", b, p, k, q_pow(b, p, k));
	return 0;
}

参考链接:

https://www.cnblogs.com/wty20010315/p/6984348.html

https://zhuanlan.zhihu.com/p/95902286

https://www.luogu.com.cn/problem/solution/P1226

posted @ 2021-02-16 14:09  VanHope  阅读(52)  评论(0编辑  收藏  举报