Description
Solution
这其实是很水的一道题。
你可以找规律,也可以推公式。
我们设前缀和为g[i],那么很明显g[i]=g[i-1]+F[i-1]。
那么现在很明显只要能递推F就好了。
我们看一下F,
F[i]=F[i−1]+(F[i]−F[i−1])
。
用f去代替后面的式子:
∑ij=0fjfi−j−∑i−1j=0fjfi−j−1=∑i−1j=0fj(fi−j−fi−j−1)+fi∗f0=F[i−2]+fi
所以
F[i]=F[i−2]+F[i−1]+fi
所以直接矩阵乘法一下就好了。
Code
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
const int mo=998244353;
typedef long long ll;
ll i,j,k,l,t,n,m,ans;
struct ju{
ll a[5][5];
ju friend operator *(ju a,ju b){
ju c;memset(c.a,0,sizeof(c.a));
int i,j,k;
fo(i,0,4){
fo(j,0,4){
fo(k,0,4){
c.a[i][j]=(c.a[i][j]+a.a[i][k]*b.a[k][j]%mo)%mo;
}
}
}
return c;
}
}a,b;
ju qsm(ju x,ll y){
ju z;
memset(z.a,0,sizeof(z.a));fo(i,0,4)z.a[i][i]=1;
while(y){
if(y&1)z=z*x;
x=x*x;
y/=2;
}
return z;
}
int main(){
scanf("%lld",&n);
a.a[0][1]=a.a[0][4]=1;
a.a[1][0]=a.a[1][1]=a.a[1][4]=1;
a.a[2][1]=a.a[2][3]=a.a[2][4]=1;
a.a[3][1]=a.a[3][2]=a.a[3][3]=a.a[3][4]=1;
a.a[4][4]=1;
b.a[0][0]=1,b.a[0][1]=2,b.a[0][2]=b.a[0][3]=1,b.a[0][4]=3;
if(!n){
printf("1\n");
return 0;
}
else{
b=b*qsm(a,n-1);
printf("%lld\n",b.a[0][4]);
}
}