1. 程式人生 > 實用技巧 >【模板】快速冪

【模板】快速冪

快速冪|二進位制取冪--$ Binary Exponentiation $

描述:

  • 應用定理: \(a^b+c=a^b+a^c,a^2b=a^b \cdot a^b=(a^b)^2\)
  • 時間複雜度: \(\mathbf{\theta}(log n)\) 時間內算出 \(a^n\)
  • 思路:
    0.1將 \(n\) 轉化為二進位制位, \(n=(n_tn_{t-1}...n_1n_0)_2\)
    0.2 \(n\)\(\left\lfloor\log_2 n \right\rfloor\) 個進位制位,所以我們算出 \(a^1,a^2,a^4,a^8,...,a^{2^\left\lfloor\log_2 n \right\rfloor}\)
    後,計算 \(\mathbf{\theta}(log n)\) 次乘法可計算出 \(a^n\)
    0.3展開即為: $$n=n_tt^t+n_{t-1}t^{t-1}+n_{t-2}t^{t-2}+...+n_12^1+n_02^0$$
    0.4其中 \(n_i\in\{0,1\}\) 那麼就有 $$a^n=(a^{n_t2^t+...+n_02^0})=a^{n_0 2^0}\times a^{n_1 2^1}\times ...\times a^{n_t 2^t}$$
    0.5即計算了 \(\mathbf{\theta}(log n)\)\(2^k\) 次冪的數,然後花費 \(\mathbf{\theta}(log n)\)
    的時間選擇二進位制為1對應的冪來相乘。

實現:

標準快速冪:

  • 遞迴:
long long int binpow(long long int a,long long int b)
{
	if(b==0)return 1;
	long long int res=binpow(a,b/2);
	return b%2?res*res*a:res*res;
}
  • 遞推:
long long int binpow(long long int a,long long int b) {
	long long int res=1;
	while(b>0)
	{
		if(b&1)res=res*a;
		a=a*a,b>>=1;
	}
	return res;
}

取模快速冪:

long long int binpow_mod(long long int a,long long int b,long long int m)
{
	a%=m;
	long long int res=1%m;
	while(b>0)
	{
		if(b&1)res=res*a%m;
		a=a*a%m;
		b>>=1;
	}
	return res;
}