JZOJ4798. 【NOIP2016提高A组模拟9.24】天使的分裂

Description

这里写图片描述

Input

一个整数n

Output

一行,一个整数,表示第0天到第n天的评估函数的值的和。

Sample Input

Input 1
5
Input 2
666666
Input 3
2147483648

Sample Output

Output 1
76
Output 2
324016098
Output 3
932937567

Data Constraint

这里写图片描述

分析

题目中的数非常特殊,是斐波拉契数列的数。
那么,这些数满足相邻两个相加可以得到一个新的数。

利用这个性质,我们可以推出递推式:
Fi=Fi1+Fi2+fi

这是一个 O(n)
可以通过矩阵乘法快速幂优化到 logn

code(c++)


#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string.h>
#include <cmath>
#include <math.h> 
#define _ %998244353
using namespace std;
struct note
{
    long long w[5];
};
long long jz[5][5]={
{0,1,0,0,0},
{1,1,1,1,0},
{0,0,0,1,0},
{0,0,1,1,0},
{1,1,1,1,1}
};
note ans;
long long s[5][5],t[5][5],n;
note times(note a)
{
    note c;
    memset(c.w,0,sizeof(c.w));
    for(int i=0;i<5;i++)
        for(int j=0;j<5;j++)
            c.w[i]=(c.w[i]+a.w[j]*s[i][j]_)_;
    return c;
}
int main()
{
    scanf("%lld",&n);
    memset(ans.w,0,sizeof(ans.w));
    memcpy(s,jz,sizeof(s));
    ans.w[0]=1;
    ans.w[1]=2;
    ans.w[2]=1;
    ans.w[3]=1;
    ans.w[4]=3;
    if(n==0)
    {
        printf("1\n");
        return 0;
    }
    n--;
    while(n)
    {
        if(n%2)ans=times(ans);
        n/=2;
        memset(t,0,sizeof(t));
        for(int i=0;i<5;i++)
            for(int j=0;j<5;j++)
                for(int k=0;k<5;k++)
                    t[i][j]=(t[i][j]+s[i][k]*s[k][j]_)_;
        memcpy(s,t,sizeof(s));
    }
    printf("%lld\n",ans.w[4]);
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值