快速幂
法一:运用位运算简化计算
以 \(3^{22}\) 为例,它的底数为 \(3\),指数为 \(22\)。指数的二进制形式为 10110
。通过二进制与十进制的转换,我们可以把 \(22\) 分解为 \(22 = 2^4 * 2^2 * 2^1\)。因此,\(3^{22} = 3^{2^4} * 3^{2^2} * 3^{2^1}\)。我们有以下几点发现:
- 1、\(2^4\), \(2^2\) 和 \(2^1\) 与二进制形式中 \(1\) 的出现位置有关,那么,这也导致 \(3^{2^4}\), \(3^{2^2}\) 和 \(3^{2^1}\) 有这样的关系。
- 2、我们知道,在二进制中,相邻的两位,从“右边到左边”要
× 2
。比如,\(2^2 = 2^1 \times 2\); 由于中间隔了一个 \(0\),所以要乘两个2
,\(2^3 = 2^2 \times 2~\Rightarrow~2^4 = 2^3 \times 2\)。反应到 \(3^{22}\) 上,就变成了平方
关系。比如,\(3^{2^2} = 3^{2^1} \times 3^{2^1}\); 由于中间隔了一个 \(0\),所以要平方
两次,\(3^{2^3} = 3^{2^2} \times 3^{2^2}~\Rightarrow~3^{2^4} = 3^{2^3} \times 3^{2^3}\)。
ll quick_pow(ll x, ll n, ll mod)
{
ll ans = 1;
while (n > 0)
{
if (n & 1)
ans = ans * x % mod;
x = x * x % mod;
n >>= 1;
}
return ans;
}
法二:运用递归的思想
对于 \(x^n\),有
\[\begin{split}
x^n = \begin{cases}
{(x^2)}^{\lfloor n / 2\rfloor}&,n为偶数 \\
{(x^2)}^{\lfloor n / 2\rfloor} \ast x&,~n为奇数
\end{cases}
\end{split}
\]
令 \(x^n =\) quick_pow(x, n)
,则递归方程:
\[\begin{split}
\text{quick\_pow(x, n)} = \begin{cases}
1&,n==0 \\
\text{quick\_pow(x, n / 2)}&,n为非0偶数 \\
\text{quick\_pow(x, n / 2)} \ast \text{x}&,n为奇数
\end{cases}
\end{split}
\]
ll quick_pow(ll x, ll n, ll mod)
{
if (n == 0) return 1;
ll ans = quick_pow1(x * x % mod, n / 2, mod);
if (n & 1) ans = ans * x % mod;
return ans;
}
完