题目
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
数据范围:
剖解题目
。。。。。
思路
一般看上去这么复杂的,肯定是递推之类的,然后对于最大的数据肯定是有快速的虽然之类的。
解法
40%:暴力
60%:预处理斐波那契数列,使用NTT计算卷积。时间复杂度Ο(nlog2 n)。
70%:可以推出F[i]=F[i-1]+F[i-2]+f[i]。时间O(n)。
100%:矩阵乘法优化:
设一个5*5的矩阵,根据矩阵乘法性质直接快速幂,然后乘一个初始的1 *5的矩阵即可。
时间O(log2 n).
代码
#include<cstdio>
#include<algorithm>
#include<cstring>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define ll long long
using namespace std;
const ll mo=998244353;
ll n,a[5]={1,1,2,1,3},ans[5];
ll sq[5][5]={0,1,1,0,1,1,1,1,0,1,0,0,1,1,1,0,0,1,0,1,0,0,0,0,1};
ll t[5][5]={1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1};
void cc1()
{
ll now[5][5];
memset(now,0,sizeof(now));
fo(i,0,4)
fo(j,0,4)
fo(k,0,4) now[i][j]=((t[i][k]*sq[k][j])%mo+now[i][j])%mo;
memcpy(t,now,sizeof(now));
}
void cc2()
{
ll now[5][5];
memset(now,0,sizeof(now));
fo(i,0,4)
fo(j,0,4)
fo(k,0,4) now[i][j]=((sq[i][k]*sq[k][j])%mo+now[i][j])%mo;
memcpy(sq,now,sizeof(now));
}
void qsm(ll n)
{
while (n){
if (n&1) cc1();
cc2();
n>>=1;
}
}
int main()
{
scanf("%lld",&n);
if (!n) {
printf("1"); return 0;
}
qsm(n-1);
fo(j,0,4)
fo(k,0,4) ans[j]=((a[k]*t[k][j])%mo+ans[j])%mo;
printf("%lld",ans[4]);
}