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;
}
posted @ 2020-07-26 18:30  GK0328  阅读(56)  评论(0编辑  收藏  举报