【牛客】斐波那契数列卷积(矩阵快速幂)(构造矩阵)

链接:https://ac.nowcoder.com/acm/contest/1087/C
 

题目描述

输入描述:

 

【牛客】斐波那契数列卷积(矩阵快速幂)(构造矩阵)_第1张图片

 

输出描述:

一行一个整数表示答案

解释:

我没做出来的原因是没推出来这个式子,矩阵的题目就是前后有联系,这样的式子我没推出来。

按照斐波那契的性质推了很久也没有发现什么公式,看题解也是直接说“很容易就得到”....不过我们可以通过直接对所求式子打表的方式来观察规律。这个打表是很容易的,只是这个规律如果对斐波那契没什么感觉的话很难观察得到(第n项等于二倍的n-1项+n-2项-二倍的n-3项-n-4项)。

推出了这个式子,我们就可以构造矩阵了,由于这个式子是4向量表示,我们要构造的矩阵也一定是四阶的,也就是说我们要构造的这个矩阵乘以n-1项就等于第n项

【牛客】斐波那契数列卷积(矩阵快速幂)(构造矩阵)_第2张图片

然后我们就可以使用矩阵快速幂递推求出,然后我们只需要寻找从0开始的次数就可以了

注意这道题的一个坑是初始矩阵的方向

#include 
#include 
#include 
#include
#include
#define ll long long
using namespace std;
#define mod 998244353
ll n;
void mul(ll f[4],ll a[4][4])
{
    ll c[4];
    memset(c,0,sizeof(c));
    for(ll j=0; j<4; j++)
        for(ll k=0; k<4; k++)
            c[j]=(c[j]+(f[k]*a[k][j])%mod)%mod;
    memcpy(f,c,sizeof(c));
}
void mulself(ll a[4][4])
{
    ll c[4][4];
    memset(c,0,sizeof(c));
    for(ll i=0; i<4; i++)
        for(ll j=0; j<4; j++)
            for(ll k=0; k<4; k++)
                c[i][j]=(c[i][j]+(a[i][k]*a[k][j])%mod)%mod;
    memcpy(a,c,sizeof(c));
}
int main()
{
    scanf("%lld",&n);
    ll f[4]= {0,0,1,2};
    ll a[4][4]= {
    {0,0,0,-1},{1,0,0,-2},{0,1,0,1},{0,0,1,2}};
    n=n;
    for(; n; n>>=1)
    {
        if(n&1)
            mul(f,a);
        mulself(a);
    }
    printf("%lld\n",(f[0]+mod)%mod);
    return 0;
}
#include 
#include 
#include 
#include
#include
#define ll long long
using namespace std;
#define mod 998244353
ll n;
void mul(ll f[4],ll a[4][4])
{
    ll c[4];
    memset(c,0,sizeof(c));
    for(ll j=0; j<4; j++)
        for(ll k=0; k<4; k++)
            c[j]=(c[j]+(f[k]*a[k][j])%mod)%mod;
    memcpy(f,c,sizeof(c));
}
void mulself(ll a[4][4])
{
    ll c[4][4];
    memset(c,0,sizeof(c));
    for(ll i=0; i<4; i++)
        for(ll j=0; j<4; j++)
            for(ll k=0; k<4; k++)
                c[i][j]=(c[i][j]+(a[i][k]*a[k][j])%mod)%mod;
    memcpy(a,c,sizeof(c));
}
int main()
{
    scanf("%lld",&n);
    if(n<=3)
    {
        if(n==1) cout<<0<>=1)
    {
        if(n&1)
            mul(f,a);
        mulself(a);
    }
    printf("%lld\n",(f[0]+mod)%mod);
}

 

你可能感兴趣的:(#,矩阵快速幂)