hdu5950——Recursive sequence

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5950

题目大意:给定一个数列,并且给出递推公式以及前两项(f[i]=f[i-1]+2*f[i-2]+i4),求这个数列的第n项对2147493647取模

 

上面是数据范围。

不难由n<231看出,O(n)肯定过不了,那只有矩阵乘法了。

i4是4维的,f[i-1],f[i-2],f[i]合起来三维,所以矩阵应该是7*7的。

它的递推矩阵为

上面的14641,1331,121,11,1全部来自于把(n+1)k展开的系数

注意点:
1.模的数是2147493647,不是2147483647

2.矩阵乘法中一定要多取模

3.要开longlong

代码:

//f[i]=2f[i-2]+f[i-1]+i*i*i*i
#include<bits/stdc++.h>

#define LL long long
#define rd(x) x=read()

using namespace std;

LL T;
LL n;
const LL mod=2147493647;

struct matrix{
    LL a[10][10];
};

inline LL read()
{
    LL f=1,x=0;char s=getchar();
    while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
    while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
    return x*f;
}

void print(matrix a)
{
    for(int i=1;i<=7;i++)
    {
        for(int j=1;j<=7;j++)
            printf("%lld ",a.a[i][j]);
        printf("\n");
    }
}

matrix init()
{
    matrix ret;
    ret.a[1][1]=1LL,ret.a[1][2]=2LL,ret.a[1][3]=1LL,ret.a[1][4]=0LL,ret.a[1][5]=0LL,ret.a[1][6]=0LL,ret.a[1][7]=0LL;
    ret.a[2][1]=1LL,ret.a[2][2]=0LL,ret.a[2][3]=0LL,ret.a[2][4]=0LL,ret.a[2][5]=0LL,ret.a[2][6]=0LL,ret.a[2][7]=0LL;
    ret.a[3][1]=0LL,ret.a[3][2]=0LL,ret.a[3][3]=1LL,ret.a[3][4]=4LL,ret.a[3][5]=6LL,ret.a[3][6]=4LL,ret.a[3][7]=1LL;
    ret.a[4][1]=0LL,ret.a[4][2]=0LL,ret.a[4][3]=0LL,ret.a[4][4]=1LL,ret.a[4][5]=3LL,ret.a[4][6]=3LL,ret.a[4][7]=1LL;
    ret.a[5][1]=0LL,ret.a[5][2]=0LL,ret.a[5][3]=0LL,ret.a[5][4]=0LL,ret.a[5][5]=1LL,ret.a[5][6]=2LL,ret.a[5][7]=1LL;
    ret.a[6][1]=0LL,ret.a[6][2]=0LL,ret.a[6][3]=0LL,ret.a[6][4]=0LL,ret.a[6][5]=0LL,ret.a[6][6]=1LL,ret.a[6][7]=1LL;
    ret.a[7][1]=0LL,ret.a[7][2]=0LL,ret.a[7][3]=0LL,ret.a[7][4]=0LL,ret.a[7][5]=0LL,ret.a[7][6]=0LL,ret.a[7][7]=1LL; 
    return ret;
}//初始化矩阵

matrix mul(matrix a,matrix b)
{
    matrix ret;
    for(int i=1;i<=7;i++)
    {
        for(int j=1;j<=7;j++)
        {
            ret.a[i][j]=0LL;
            for(int k=1;k<=7;k++)
                ret.a[i][j]+=(a.a[i][k]*b.a[k][j])%mod,ret.a[i][j]%=mod;//血的教训
        }
    }
    //print(ret);
    return ret;
}//矩阵乘法

matrix fast_power(matrix a,LL x)
{
    matrix ret;
    for(int i=1;i<=7;i++)
    {
        for(int j=1;j<=7;j++)
        {
            if(i==j)ret.a[i][j]=1LL;
            else ret.a[i][j]=0LL;
        }
    }
    while(x)
    {
        if(x&1)ret=mul(ret,a);
        a=mul(a,a);
        x>>=1;
    }
    return ret;
} //快速幂

LL calc(matrix a,LL b,LL c){return ((a.a[1][1]*c)%mod+(a.a[1][2]*b)%mod+(a.a[1][3]*81)%mod+(a.a[1][4]*27)%mod+(a.a[1][5]*9)%mod+(a.a[1][6]*3)%mod+(a.a[1][7])%mod)%mod;}//由矩阵算答案

int main()
{
    rd(T);
    while(T--)
    {
        LL a,b,c;
        rd(a),rd(b),rd(c);
        LL ret;
        if(a==1)ret=b%mod;
        else if(a==2)ret=c%mod;//特判
        else 
        {
            matrix ans=init();
            ans=fast_power(ans,a-2);
            //print(ans);
            ret=calc(ans,b,c);
        }
        printf("%lld\n",ret);
    }
    return 0;
}

屈辱历史:

 

转载于:https://www.cnblogs.com/Robin20050901/p/10181708.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值