本文写于2017-11-09,其中的一些思路和基础知识可能存在问题,公式也未用LATEX编写。本文移至此处时暂未重新学习。

    求递推数列的第N项,通常做法的复杂度大概是O(n)
    使用矩阵加速幂可以把复杂度降到O(log n)
    大体遇到的问题:

    1. 递推数列化为矩阵
    2. 矩阵乘法

    第一个问题,大概是这样的:
    矩阵加速幂求递推数列的项 - 图1

    第二个问题就是矩阵乘法啦!
    ~~

    1. //对于f[n]=∑a[i]*f[n-i]
    2. #include<iostream>
    3. #include<cstdio>
    4. #include<algorithm>
    5. #include<cstring>
    6. using namespace std;
    7. struct sq{long long a[105][105];}base,mu,ans;
    8. void init(sq &_1){memset(_1.a,0,sizeof(_1.a));}
    9. int m,n;//m 公式中i取值的最大值(即f[n]与f[n-1]~f[n-m-1]直接相关) n 所求的f[n]
    10. long long mod;
    11. sq mul(sq _1,sq _2)//两个m*m的矩阵相乘
    12. {
    13. sq ans;
    14. init(ans);
    15. for(int i=1;i<=n;i++)
    16. for(int j=1;j<=n;j++)
    17. for(int k=1;k<=n;k++)
    18. ans.a[i][j]+=_1.a[i][k]*_2.a[k][j]%mod,
    19. ans.a[i][j]%=mod;
    20. return ans;
    21. }
    22. sq spow(sq _1,long long k)
    23. {
    24. sq base=_1,ans=_1;
    25. k--;
    26. while(k)
    27. {
    28. if(k&1) ans=mul(ans,base);
    29. base=mul(base,base);
    30. k>>=1;
    31. }
    32. return ans;
    33. }
    34. sq amul(sq _1,sq _2)
    35. {
    36. sq ans;
    37. init(ans);
    38. for(int i=1;i<=n;i++)
    39. for(int j=1;j<=n;j++)
    40. ans.a[1][i]+=_1.a[j][1]*_2.a[j][i]%mod,
    41. ans.a[1][i]%=mod;
    42. return ans;
    43. }
    44. void build_sq()
    45. {
    46. init(base);
    47. for(int i=1;i<=m;i++) cin>>base.a[1][i];//读入f[n-i]的系数a[i]
    48. for(int j=1;j<m;j++) base.a[j+1][j]=1; //把base矩阵建好
    49. for(int i=1;i<=m;i++) cin>>mu.a[m-i+1][1];//读入f[1]~f[m]
    50. }
    51. int main()
    52. {
    53. ios::sync_with_stdio(false);
    54. cin>>m>>n>>mod;
    55. build_sq();//把矩阵存好!
    56. sq ans=amul(mu,spow(base,n-m));
    57. cout<<ans.a[1][1]<<endl;
    58. return 0;
    59. }

    这个代码没有对应任何题,所以不知道对不对