快速幂

法一:运用位运算简化计算

\(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;
}

posted @ 2024-02-15 14:48  ltign  阅读(6)  评论(0编辑  收藏  举报