浅谈快速幂

\(a^b\),先上代码吧

int qsm(int a,int b){
	int ans = 1,base = a;
	while(b){
		if(b&1) ans *= base;
		base *= base;
		b>>=1;
	}
	return ans;
}

\(a = 3, b = 21\) 为例

\(①\) \(:\) \(b >>= 1\) (位运算,就是除以2)是快速幂加速的关键, 它将线性的时间复杂度 \(b\) 降为 \(log_2b\),效果体现就是去掉尾数后各位数往低位移一位.如\(10101\) (\(21\)) 变为 \(1010\) (\(10\)).

\(②\) \(:\) \(base = base \times base\),这一步是配合 \(①\) 不断积累 \(base\).(\(base = a^1,a^2,a^4\),\(a^8\),\(a^{16}\)......)

\(③\) \(:\) \(b\)&\(1\)则是判断尾位是否为\(1\),是\(1\)就将\(②\)中累积\(base\)乘上.

解释例子:
\(①\) \(b = 10101\),尾数为\(1\)\(ans\) 乘上 \(base\)\(3^1\)\(b\) 变为 \(1010\) ,\(base\) 积累为 \(3^2 = 4\).

\(②\) \(b = 1010\),尾数为\(0\)\(b\) 变为了 \(101\), \(base\) 积累为 \(3^2 \times 3^2 = 3^4\).

\(③\) \(b = 101\),尾数为\(1\), \(ans\) 乘上 \(base\)\(3^1 \times 3^4\), \(b\) 变为\(10\), \(base\)积累为 \(3^{8}\).

\(④\) \(b = 10\),尾数为\(0\), \(b\)变为\(1\),\(base\)积累为 \(3^{16}\).

\(⑤\) \(b = 1\), 尾数为\(1\)\(ans\) 乘上 \(base\)\(3^1 \times 3^4 \times 3^{16}\), \(b\)变为了\(0\), \(base\)积累为 \(3^{32}\),得到了答案\(ans\),由于下一步\(b = 0\), 程序退出.

整体来看,\(ans\) = \(3^1 \times 3^4 \times 3^{16}\) = \(3^{21}\),其中指数 \(1,4,16\) 恰对应 \(10101\)\(1\)的位置(\(2^0,2^2,2^4\)).


曾经思考快速幂利用二进制加速,那么利用更高进制的加速岂不更快?

思考一下便打消了这种想法:其他进制不如二进制方便.二进制将数分解为\(1 \times 2^a+ 1 \times 2^b......\) 前面有默认系数1,可对于其他进制的系数则有(1,2,......), \(②\) 中的 \(base\) 根本积累不了.

posted @ 2021-10-04 16:00  xqy2003  阅读(43)  评论(0)    收藏  举报