快速幂与矩阵快速幂
利用二进制拆分可将形如求\(a^{n}\)的问题的复杂度从\(O(n)\)降至\(O(\log n)\)
可求出\(a\),\(a^{2}\),……,\(a^{k}\)
若n的二进制表示下的第k位为1则乘上\(a^{k}\),否则跳过
自然语言是多么无力啊
看代码会比较好
int ksm(int a,int n)
{
int ans=1;
while(n)
{
if(n&1) ans*=a;//求出当前的最后一位是否为1
a*=a;
n>>=1;//舍弃掉最后一位,原来的第k位变为k-1位(其实就是左移)
}
return ans;
}
我们可以用快速幂的思想来解决掉一些递推问题
例子:fibbonaci数列第n项
其定义为
\[ f(x)=\left \{
\begin{aligned}
& 1 & i=1,2 \newline
& f(i-1)+f(i-2) & i>2
\end{aligned}
\right.
\]
显然用记忆化只能将复杂度降到\(O(n)\)
显然有
\[ \left[
\begin{matrix}
1 & 1 \newline
1 & 0 \newline
\end{matrix}
\right]
*
\left[
\begin{matrix}
f[i-1] \newline
f[i-2]
\end{matrix}
\right]
=
\left[
\begin{matrix}
f[i] \newline
f[i-1]
\end{matrix}
\right]
\]
markdown矩阵好难打啊
因此有
\[\left[
\begin{matrix}
f[i] \newline
f[i-1]
\end{matrix}
\right]
=
\left[
\begin{matrix}
1 & 1 \newline
1 & 0 \newline
\end{matrix}
\right]^{i-1}
*
\left[
\begin{matrix}
f[2] \newline
f[1]
\end{matrix}
\right]
\]
这和上面的快速幂形式是一样的
因此我们称其为矩阵快速幂
上代码
struct Matrix
{
int a[2][2];
void clear()
{
memset(a,0,sizeof(a));
}
int* operator [] (const int x)
{
return a[x];
}
friend Matrix operator * (Matrix a,Matrix b)
{
Matrix c;
c.clear();
for(int k=0;k<2;++k)
for(int i=0;i<2;++i)
for(int j=0;j<2;++j)
c[i][j]+=a[i][k]*b[k][j];
return c;
}
}base,ans;
base初始化为要乘的矩阵,ans初始化为初值(即左边那条线为1,右边为0)
这种问题的难点就是要推出要乘的矩阵,推出来了就好办了
板子题洛谷P1962
一切伟大的行动和思想,都有一个微不足道的开始。
There is a negligible beginning in all great action and thought.
There is a negligible beginning in all great action and thought.