HDU3306 Another kind of Fibonacci
http://acm.hdu.edu.cn/showproblem.php?pid=3306
矩阵快速幂
构造矩阵
\[\begin{equation}
\left[
\begin{array}{cc}
X & Y \\
1 & 0 \\
\end{array}
\right]
\end{equation}
\]
容易转移求出\(A_{n}\)
那么\(S_{n}\)该如何求呢?
\[S_{n}=S_{n-1}+A_{n}^2\\
=S_{n-1}+(X*A_{n-1}+Y*A_{n-2})^2\\
=S_{n-1}+X^2A_{n-1}^2+Y^2A_{n-2}^2+2XYA_{n-1}A_{n-2}\\
处理2XYA_{n-1}A_{n-2}\\
A_{n}A_{n-1}=(X*A_{n-1}+Y*A_{n-2})*A_{n-1}\\
=XA_{n-1}^2+YA_{n-1}A_{n-2}\\
\begin{cases}
S_{n}=1*S_{n-1}+X^2A_{n-1}^2+Y^2A_{n-2}^2+2XYA_{n-1}A_{n-2}\\
A_{n}^2=0*S_{n-1}+X^2A_{n-1}^2+Y^2A_{n-2}^2+2XYA_{n-1}A_{n-2}\\
A_{n-1}^2=0*S_{n-1}+1*A_{n-1}^2+0*A_{n-2}^2+0*A_{n-1}A_{n-2}\\
A_{n}A_{n-1}=0*S_{n-1}+XA_{n-1}^2+0*A_{n-2}^2+Y*A_{n-1}A_{n-2}
\end{cases}\\
矩阵有了,剩下的都是板子
\]
套路:把与所求的项有关的项都找出来,尝试建立递推式的方程组,建完就结束了
\(C++ Code:\)
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#define mod 10007
#define ll long long
#define m 4
using namespace std;
ll n,x,y;
struct mat
{
ll a[m+1][m+1];
mat operator * (mat b)
{
mat c;
for (int i=1;i<=m;i++)
for (int j=1;j<=m;j++)
c.a[i][j]=0;
for (int k=1;k<=m;k++)
for (int i=1;i<=m;i++)
for (int j=1;j<=m;j++)
c.a[i][j]=(c.a[i][j]+a[i][k]*b.a[k][j])%mod;
return c;
}
}zero,cs,zy,ans;
mat ksm(mat x,ll y)
{
mat ans=zero;
while (y)
{
if (y&1)
ans=ans*x;
x=x*x;
y >>=1;
}
return ans;
}
int main()
{
for (int i=1;i<=m;i++)
zero.a[i][i]=1;
cs.a[1][1]=2,cs.a[2][1]=1,cs.a[3][1]=1,cs.a[4][1]=1;
while (scanf("%lld%lld%lld",&n,&x,&y)!=EOF)
{
x%=mod,y%=mod;
zy.a[1][1]=1,zy.a[1][2]=x*x%mod,zy.a[1][3]=y*y%mod,zy.a[1][4]=x*y%mod*2%mod;
zy.a[2][2]=x*x%mod,zy.a[2][3]=y*y%mod,zy.a[2][4]=x*y%mod*2%mod;
zy.a[3][2]=1;
zy.a[4][2]=x,zy.a[4][4]=y;
ans=ksm(zy,n-1)*cs;
cout << ans.a[1][1] << endl;
}
return 0;
}