【2016-沈阳赛区现场赛-C】

跟斐波那契数列很像的递推,要加上i^4,用到二项式定理,使用矩阵快速幂,矩阵为7阶。


递推矩阵为

ll qiqi[10][10]=
{
    {0,0,0,0,0,0,0,0},
    {0,1,2,1,4,6,4,1},
    {0,1,0,0,0,0,0,0},
    {0,0,0,1,4,6,4,1},
    {0,0,0,0,1,3,3,1},
    {0,0,0,0,0,1,2,1},
    {0,0,0,0,0,0,1,1},
    {0,0,0,0,0,0,0,1}
};

从1开始。


基础矩阵为

{b}

{a}

{16}

{8}

{4}

{2}

{1}


快速幂一下然后乘起来就是答案。

就是你需要f(n+1),所以你要提供f(n),f(n-1),n^4

你需要f(n+1),f(n),(n+1)^4,所以你需要提供n^3,n^2,n^1,1。

然后就全了,比较一下新旧状态就很容易得到转移矩阵,无非就是需要哪些项,然后给个系数就OK。


代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const ll mod=2147493647ll;

ll qiqi[10][10]=
{
    {0,0,0,0,0,0,0,0},
    {0,1,2,1,4,6,4,1},
    {0,1,0,0,0,0,0,0},
    {0,0,0,1,4,6,4,1},
    {0,0,0,0,1,3,3,1},
    {0,0,0,0,0,1,2,1},
    {0,0,0,0,0,0,1,1},
    {0,0,0,0,0,0,0,1}
};

struct jz
{
    ll MAP[10][10];
    ll m,n;
    void init1(ll a,ll b)
    {
        m=7;
        n=1;
        MAP[1][1]=b;
        MAP[2][1]=a;
        MAP[3][1]=16;
        MAP[4][1]=8;
        MAP[5][1]=4;
        MAP[6][1]=2;
        MAP[7][1]=1;
    }
    void init2()
    {
        m=n=7;
        for(ll i=1;i<=7;i++)
            for(ll j=1;j<=7;j++)
                MAP[i][j]=qiqi[i][j];
    }
    jz operator * (const jz& rhs) const
    {
        jz ret;
        ret.m=m;
        ret.n=rhs.n;
        for(ll i=1;i<=ret.m;i++)
            for(ll j=1;j<=ret.n;j++)
            {
                ret.MAP[i][j]=0;
                for(ll k=1;k<=n;k++)
                    ret.MAP[i][j]=(ret.MAP[i][j]+(MAP[i][k]*rhs.MAP[k][j])%mod)%mod;
            }
        return ret;
    }
    jz operator ^ (ll n) const
    {
        jz ret;
        jz x=*this;
        ret.m=ret.n=m;
        memset(ret.MAP,0,sizeof(ret.MAP));
        for(ll i=1;i<=m;i++) ret.MAP[i][i]=1;
        while(n)
        {
            if(n&1) ret=ret*x;
            x=x*x;
            n>>=1;
        }
        return ret;
    }
    void prll()
    {
        for(ll i=1;i<=m;i++)
        {
            for(ll j=1;j<=n;j++)
                printf("%I64d ",MAP[i][j]);
            puts("");
        }
    }
};

int main()
{
    ll T;
    scanf("%I64d",&T);
    while(T--)
    {
        ll N,a,b;
        scanf("%I64d %I64d %I64d",&N,&a,&b);
        if(N==1) printf("%I64d\n",a);
        else if(N==2) printf("%I64d\n",b);
        else
        {
            jz hehe;
            hehe.init2();
            jz haha;
            haha.init1(a,b);
            hehe=hehe^(N-2);
            //hehe.prll();
            haha=hehe*haha;
            printf("%I64d\n",haha.MAP[1][1]);
        }
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值