本文写于2017-11-09,其中的一些思路和基础知识可能存在问题,公式也未用LATEX编写。本文移至此处时暂未重新学习。
求递推数列的第N项,通常做法的复杂度大概是O(n)
使用矩阵加速幂可以把复杂度降到O(log n)
大体遇到的问题:
- 递推数列化为矩阵
- 矩阵乘法
第一个问题,大概是这样的:
第二个问题就是矩阵乘法啦!
~~
//对于f[n]=∑a[i]*f[n-i]
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
struct sq{long long a[105][105];}base,mu,ans;
void init(sq &_1){memset(_1.a,0,sizeof(_1.a));}
int m,n;//m 公式中i取值的最大值(即f[n]与f[n-1]~f[n-m-1]直接相关) n 所求的f[n]
long long mod;
sq mul(sq _1,sq _2)//两个m*m的矩阵相乘
{
sq ans;
init(ans);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
for(int k=1;k<=n;k++)
ans.a[i][j]+=_1.a[i][k]*_2.a[k][j]%mod,
ans.a[i][j]%=mod;
return ans;
}
sq spow(sq _1,long long k)
{
sq base=_1,ans=_1;
k--;
while(k)
{
if(k&1) ans=mul(ans,base);
base=mul(base,base);
k>>=1;
}
return ans;
}
sq amul(sq _1,sq _2)
{
sq ans;
init(ans);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
ans.a[1][i]+=_1.a[j][1]*_2.a[j][i]%mod,
ans.a[1][i]%=mod;
return ans;
}
void build_sq()
{
init(base);
for(int i=1;i<=m;i++) cin>>base.a[1][i];//读入f[n-i]的系数a[i]
for(int j=1;j<m;j++) base.a[j+1][j]=1; //把base矩阵建好
for(int i=1;i<=m;i++) cin>>mu.a[m-i+1][1];//读入f[1]~f[m]
}
int main()
{
ios::sync_with_stdio(false);
cin>>m>>n>>mod;
build_sq();//把矩阵存好!
sq ans=amul(mu,spow(base,n-m));
cout<<ans.a[1][1]<<endl;
return 0;
}
这个代码没有对应任何题,所以不知道对不对