本篇题解用于作者本人对于矩阵乘法的印象加深,也欢迎大家的阅读。


题目大意

众所周知,斐波那契数列为 \(f(0)=1\) , \(f(1)=1\) ,\(f(n)=f(n-1)+f(n-2)~(n>=2)\) 。

定义另一种斐波那契数列: \(A(0)=1\) , \(A(1)=1\) , \(A(n)=x*A(n-1)+y*A(n-2)~(n>=2)\) 。

我们要计算 \(S(n)\) , \(S(n)=A(0)^2+A(1)^2+...+A(n)^2\) 。

题解

我们可以很轻易的发现这是一道矩阵乘法的题,因为他是求关于一个递推式的平方和,而本题的难点就在于如何构建出合适的加速矩阵。

本题求的是 \(S(n)\) ,所以我们可以从 \(S(n)\) 递推式入手。

\[S(n)=S(n-1)+A^2(n)
\]

所以, \(A^2(n)\) 肯定要列入我们的矩阵中。我们再来看看 \(A^2(n)\) 的递推式:

\[\begin{array}{}
A^2(n)=(x*A(n-1)+y*A(n-2))^2\\
\\
=x^2A^2(n-1)+2xyA(n-1)A(n-2)+y^2A^2(n-2)\\
\end{array}
\]

所以, \(A^2(n)\) , \(A(n)A(n-1)\) 和 \(A^2(n-1)\) 也是需要加入矩阵的。因此我们的状态矩阵就是:

\[\left[\begin{matrix}
S(n)&A^2(n)&A^2(n-1)&A(n)A(n-1)\\
\end{matrix}\right]
\]

其中每一个元素的递推式如下:

\[\begin{array}{}
S(n)=S(n-1)+x^2A^2(n-1)+2xyA(n-1)A(n-2)+y^2A^2(n-2)\\
\\
A^2(n)=x^2A^2(n-1)+2xyA(n-1)A(n-2)+y^2A^2(n-2)\\
\\
A^2(n-1)=A^2(n-1)\\
\\
A(n)A(n-1)=xA^2(n-1)+yA(n-1)A(n-2)
\end{array}
\]

我们再根据状态矩阵以及状态矩阵元素的递推式,我们可以求出加速矩阵:

\[\left[\begin{matrix}
1&0&0&0\\
x^2&x^2&1&x\\
y^2&y^2&0&0\\
2xy&2xy&0&y\\
\end{matrix}\right]
\]

即:

\[\begin{array}{}
\left[\begin{matrix}
S(n-1)&A^2(n-1)&A^2(n-2)&A(n-1)A(n-2)\\
\end{matrix}\right]
*
\left[\begin{matrix}
1&0&0&0\\
x^2&x^2&1&x\\
y^2&y^2&0&0\\
2xy&2xy&0&y\\
\end{matrix}\right]
=
\left[\begin{matrix}
S(n)&A^2(n)&A^2(n-1)&A(n)A(n-1)\\
\end{matrix}\right]\\

\end{array}
\]

最后我们再套一个矩阵快速幂的模板就可以了。

代码如下:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int MOD=10007;
struct Matrix
{
int n,m;
ll h[5][5];
Matrix()
{
memset(h,0,sizeof(h));
}
void Re1(int a)
{
n=m=a;
memset(h,0,sizeof(h));
for(int i=1;i<=a;++i)
h[i][i]=1;
}
};
Matrix operator * (const Matrix a,const Matrix b)
{
Matrix ans;
ans.n=a.n;
ans.m=b.m;
for(int i=1;i<=a.n;++i)
{
for(int j=1;j<=b.m;++j)
{
for(int k=1;k<=a.m;++k)
{
ans.h[i][j]+=a.h[i][k]*b.h[k][j]%MOD;
ans.h[i][j]%=MOD;
}
}
}
return ans;
}
Matrix operator ^ (const Matrix xx,const ll kk)
{
Matrix ans,x=xx;
ll k=kk;
ans.Re1(4);
while(k>0)
{
if(k&1)
ans=ans*x;
x=x*x;
k>>=1;
}
return ans;
}
int n;
ll x,y;
Matrix tmp,stp,ans;
int main()
{
tmp.n=1;
tmp.m=4;
tmp.h[1][1]=2;
tmp.h[1][2]=1;
tmp.h[1][3]=1;
tmp.h[1][4]=1;
while(cin>>n>>x>>y)
{
stp.n=stp.m=4;
stp.h[1][1]=stp.h[2][3]=1;
stp.h[2][1]=stp.h[2][2]=x*x%MOD;
stp.h[3][1]=stp.h[3][2]=y*y%MOD;
stp.h[4][1]=stp.h[4][2]=2*x*y%MOD;
stp.h[2][4]=x;
stp.h[4][4]=y;
ans=tmp*(stp^(n-1));
printf("%lld\n",ans.h[1][1]);
}
}

最新文章

  1. ecshop编辑器FCKeditor修改成KindEditor编辑批量上传图片
  2. socket.io 中文手册 中文文档
  3. Javascript面向对象编程
  4. Python3 基本数据类型注意事项
  5. Android简单计算器
  6. C#Dictionary集合的使用
  7. Mysql的转义字符
  8. jQuery(6)——jQuery对表单、表格的操作及更多应用
  9. luogu 访问”美术馆“ &amp;&amp; 偷天换日
  10. 新概念英语(1-69)The car race
  11. Python3 与 C# 并发编程之~ 线程篇
  12. Docker容器服务发现方案
  13. WPF下载文件并且动态显示进度
  14. ​ oracle分区表(附带按照月自动分区、按天自动分区)
  15. Oracle_PL/SQL(2) 过程控制
  16. 繁体简体转化_langconv.py
  17. security/pam_appl.h:没有那个文件或目录
  18. sqlserver 2008 开启CLR
  19. 总结web应用中常用的各种cache(转)
  20. CF 1023D Array Restoration - 线段树

热门文章

  1. shell编程之字符串操作
  2. 不小心清空了Ceph的OSD的分区表如何恢复
  3. 解决自动安装Freebsd系统盘符无法确定问题
  4. Java(三)常用类
  5. 鸿蒙系统freeModbusTcp移植简介
  6. 阿里面试官:小伙子,你给我说一下Spring Bean初始化的几种常规方式吧
  7. IDEA创建WebService服务端与客户端
  8. Folx的分类标签规则怎么自定义
  9. Comparator比较器
  10. leetcode116. 填充每个节点的下一个右侧指针