为什么要演奏春日影

先挂上题目传送门吧。

题目大意

输入 \(n,d,m\),计算 \(\frac{f_{nd}}{f_d} \bmod m\)

解题思路

首先,我们需要知道一个引理:\(f_{x+y}=f_{x+1}f_y + f_xf_{y-1}\)

可以用数学归纳法证明,对于 \(b=0\) 或者 \(b=1\),该式显然成立。如果对于 \(b=k\)\(b=k-1\) 等式成立,那么就有:

\[\begin{cases} f_{a+k}=f_{a+1}f_k + f_a f_{k-1}\\ f_{a+k-1}=f_{a+1}f_{k-1}+f_a f_{k-2} \end{cases} \]

将两式相加,就有 \(f_{a+k+1}=f_{a+1}f_{k+1}+f_{a}f_{k}\),也就是说,对于 \(b=k+1\) 等式也成立,归纳完成。

应用该定理就可以得到:

\[f_{kd}=f_{d+1}f_{(k-1)d}+f_df_{(k-1)d-1}\\ f_{kd-1}=f_{d}f_{(k-1)d}+f_{d-1}f_{(k-1)d-1} \]

我们令 \(g_k=\frac{f_{kd}}{f_d},h_k=f_{kd-1}\),那么第一个式子就变成了:

\[f_dg_k=f_{d+1}g_{k-1}f_d+f_dh_{k-1} \]

两边同时除以 \(f_d\) 就有:

\[g_k=f_{d+1}g_{k-1}+h_{k-1} \]

再观察第二个式子:

\[h_k={f_d}^2g_{k-1}+f_{d-1}h_{k-1} \]

我们可以先用计算出 \(f_{d-1},{f_d}^2,f_{d+1}\) 作为矩阵快速幂的参数后用矩阵快速幂计算 \(g_k\)

#include<bits/stdc++.h>
using namespace std;
#define int long long
int t,n,d,m;
struct Matrix
{
    int a[2][2];
    Matrix(){a[0][0]=a[1][0]=a[0][1]=a[1][1]=0;}
    Matrix operator * (const Matrix &x) const
    {
        Matrix res;
        for(int i=0;i<2;i++)
        {
            for(int j=0;j<2;j++)
            {
                for(int k=0;k<2;k++)
                res.a[i][j]=(res.a[i][j]+a[i][k]*x.a[k][j])%m;
            }
        }
        return res;
    }
};
Matrix qpow(Matrix a,int b)
{
    if(b==0)
    {
        Matrix res;
        res.a[0][0]=res.a[1][1]=1;
        return res;
    }
    if(b==1) return a;
    if(b==2) return a*a;
    Matrix res=a;
    b--;
    while(b)
    {
        if(b&1) res=res*a;
        a=a*a;
        b>>=1;
    }
    return res;
}
signed main()
{
    cin>>t;
    while(t--)
    {
        cin>>n>>d>>m;
        Matrix base,sec_base,thd_base,fth_base;
        fth_base.a[0][0]=thd_base.a[0][1]=sec_base.a[0][0]=base.a[0][0]=base.a[0][1]=base.a[1][0]=1;
        Matrix ans1=qpow(base,d-1)*sec_base;
        thd_base.a[0][0]=(ans1.a[0][0]+ans1.a[1][0])%m;
        thd_base.a[1][0]=(ans1.a[0][0]*ans1.a[0][0])%m;
        thd_base.a[1][1]=ans1.a[1][0];
        fth_base.a[1][0]=ans1.a[1][0];
        Matrix ans2=qpow(thd_base,n-1)*fth_base;
        cout<<ans2.a[0][0]<<'\n';
    }
    return 0;
}
posted @ 2026-08-17 17:56  ryderyang  阅读(0)  评论(0)    收藏  举报