FZU1683---纪念SlingShot(矩阵快速幂(数据劣质))

本文介绍了一种使用矩阵快速幂求解特定递推数列的方法,通过构造特定的系数矩阵并利用快速幂技巧,可以高效地计算出数列的第n项。特别针对不符合常规递推边界条件的问题给出了实现细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

【题目来源】https://vjudge.net/problem/FZU-1683
【题意】
题意就像题面描述。
【思路】
这道题和我上一道题Arc of Dream非常相似,并且我在那篇博客里也写的非常详细,所以这里就直接写怎么推导:
设前n项和:S
那么:S[i]=S[i-1]+F[i]
接着:F[i]=3*F[i-1]+2*F[i-2]+7*F[i-3]
代入:S[i]=S[i-1]+3*F[i-1]+2*F[i-2]+7*F[i-3]。
写出系数矩阵:
1 3 2 7
0 3 2 7
0 1 0 0
0 0 1 0
然后,必须强调的一点就是,这道题的数据不符合题意范围:
明明是n>=3,却依旧存在n<3的情况。。。
【代码】

#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
using namespace std;
const LL mod=2009;
struct mat
{
    LL a[5][5];
};
mat operator*(mat &s,mat &t)
{
    mat r;
    memset(r.a,0,sizeof(r.a));
    for(int i=1; i<=4; i++)
    {
        for(int j=1; j<=4; j++)
        {
            for(int k=1; k<=4; k++)
            {
                r.a[i][j]+=s.a[i][k]*t.a[k][j];
                if(r.a[i][j]>=mod)
                    r.a[i][j]%=mod;
            }
        }
    }
    return r;
}
LL pow_mat(mat base,LL k)
{
    mat ans;
    for(int i=1; i<=4; i++)
        for(int j=1; j<=4; j++)
            ans.a[i][j]=(i==j);
    while(k)
    {
        if(k&1)
        {
            ans=ans*base;
        }
        base=base*base;
        k>>=1;
    }
    return (ans.a[1][1]*9+ans.a[1][2]*5+ans.a[1][3]*3+ans.a[1][4])%mod;
}
int main()
{
    int T,cases=1;
    scanf("%d",&T);
    while(T--)
    {
        int n;
        scanf("%d",&n);
        if(n==0)
            printf("Case %d: 1\n",cases++);
        else if(n==1)
            printf("Case %d: 4\n",cases++);
        else if(n==2)
            printf("Case %d: 9\n",cases++);
        else
        {
            mat base;
            memset(base.a,0,sizeof(base.a));
            base.a[1][1]=1;
            base.a[1][2]=3;
            base.a[1][3]=2;
            base.a[1][4]=7;
            base.a[2][2]=3;
            base.a[2][3]=2;
            base.a[2][4]=7;
            base.a[3][2]=1;
            base.a[4][3]=1;
            LL ans=pow_mat(base,n-2);
            printf("Case %d: %lld\n",cases++,ans);
        }

    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值