一个自然数k可以写成
k
=
∑
1
n
a
i
∗
2
i
,
a
i
∈
{
0
,
1
}
k=\sum_1^na_i*2^i,a_i\in\{0,1\}
k=∑1nai∗2i,ai∈{0,1}的形式。快速幂的思想就基于此。
比如
a
21
=
a
(
1
∗
2
0
+
1
∗
2
2
+
1
∗
2
4
)
=
a
1
∗
a
4
∗
a
16
a^{21}=a^{(1*2^0+1*2^2+1*2^4)} =a^1*a^4*a^{16}
a21=a(1∗20+1∗22+1∗24)=a1∗a4∗a16
C++:(mod为要取模的数,无则删去)
double pow(double a,long long k)
{
if(a==0)
return 0;
double ans=1;
int NF=0;
if(k<0)
{
k=-k;
NF=1;
}
while(k)
{
if(k&1)
ans=ans*a%mod;
a=(a*a)%mod;//a=a^i%mod
k>>=1;
}
if(NF)
return 1/ans;
return ans;
}
矩阵快速幂
vector<vector<long long>> matrix_multiply(const vector<vector<long long>> &a,const vector<vector<long long>> &b)
{
int r=a.size(),c=a[0].size();
vector<vector<long long>> ans(r,vector<long long>(c));
for(int i=0;i<r;i++)
{
for(int j=0;j<c;j++)
ans[i][j]=a[i][0]*b[0][j]+a[i][1]*b[1][j];
}
return ans;
}
vector<vector<long long>> matrixPow(vector<vector<long long>> a,int n)
{
vector<vector<long long>> ret={{1,0},{0,1}};//initialize as you need
while(n>0)
{
if(n&1)
ret=matrix_multiply(ret,a);
n>>=1;
a=matrix_multiply(a,a);
}
return ret;
}
当一个式子为齐次线性递推式时,就可以把数列的递推关系转化为矩阵的递推关系,即构造出一个矩阵的n次方乘以一个列向量得到一个列向量,这个列向量中包含我们要求的 f(n)。