幸 福 \color{blue}{幸福} 幸福
Time Limit: 1S | Memory Limit: 256MB | |
---|---|---|
Total Submissions: 652 | Accepted: 111 |
D
e
s
c
r
i
p
t
i
o
n
\color{blue}{Description}
Description
在只有纯白的世界里,栋栋和糯糯开始构建世界的色彩。
在第 0 0 0 天,他们相爱并创造了一颗爱心,这颗爱心由栋栋拿着。
接下来的每一天,栋栋和糯糯都将手里的爱心全部递给对方,然后栋栋会再从手中再生出与其今天给出的相同数量的爱心。
即,若令第 ii 天的栋栋手里爱心的数目为 f i f_i fi,那么 f f f 满足 f 0 = 1 , f 1 = 1 , f i = f i − 1 + f i − 2 ( i > 1 ) f_0=1,f_1=1,f_i=f_{i−1}+f_{i−2}(i>1) f0=1,f1=1,fi=fi−1+fi−2(i>1) 。
不断再生并相互传递爱心会产生幸福,栋栋的幸福度被认为是其每天手里的爱心数的一个卷积,即 F n = ∑ i = 0 n f i f n − i F_n=∑^n_{i=0}f_if_{n−i} Fn=∑i=0nfifn−i 。
本是一成不变的风景中,两人逐渐被越来越多的爱心围绕。糯糯想要知道,从第 0 0 0 天到第 n n n天栋栋一共收获了多少幸福呢?即要求你计算 ∑ i = 0 n F i ∑_{i=0}^nF_i ∑i=0nFi 。由于栋栋肯定很幸福,答案也可能很大,她只需要你将答案对 998244353 998244353 998244353 取模。
I
n
p
u
t
\color{blue}{Input}
Input
一行,一个整数
n
n
n 。
O
u
t
p
u
t
\color{blue}{Output}
Output
一行,一个整数,表示第
0
0
0 天到第
n
n
n 天的栋栋的幸福度的和。
S
a
m
p
l
e
I
n
p
u
t
\color{blue}{Sample\ Input}
Sample Input
5
S
a
m
p
l
e
O
u
t
p
u
t
\color{blue}{Sample\ Output}
Sample Output
76
推一下公式:
F
n
=
∑
i
=
0
n
f
i
f
n
−
i
F_n=\sum_{i=0}^{n}f_if_{n-i}
Fn=∑i=0nfifn−i
=
f
0
f
n
+
f
1
f
n
−
1
+
∑
i
=
2
n
f
i
f
n
−
i
\ \ \ \ \ \ =f_0f_n+f_1f_{n-1}+\sum_{i=2}^nf_if_{n-i}
=f0fn+f1fn−1+∑i=2nfifn−i
=
f
0
f
n
+
f
1
f
n
−
1
+
∑
i
=
2
n
(
f
i
−
1
+
f
i
−
2
)
f
n
−
i
\ \ \ \ \ \ =f_0f_n+f_1f_{n-1}+\sum_{i=2}^n(f_{i-1}+f_{i-2})f_{n-i}
=f0fn+f1fn−1+∑i=2n(fi−1+fi−2)fn−i
=
f
0
f
n
+
f
1
f
n
−
1
+
∑
i
=
2
n
(
f
i
−
1
f
n
−
i
+
f
i
−
2
f
n
−
i
)
\ \ \ \ \ \ =f_0f_n+f_1f_{n-1}+\sum_{i=2}^n{(f_{i-1}f_{n-i}+f_{i-2}f_{n-i})}
=f0fn+f1fn−1+∑i=2n(fi−1fn−i+fi−2fn−i)
=
f
0
f
n
+
f
1
f
n
−
1
+
∑
i
=
2
n
f
i
−
1
f
n
−
i
+
∑
i
=
2
n
f
i
−
2
f
n
−
i
\ \ \ \ \ \ =f_0f_n+f_1f_{n-1}+\sum_{i=2}^n{f_{i-1}f_{n-i}}+\sum_{i=2}^{n}{f_{i-2}f_{n-i}}
=f0fn+f1fn−1+∑i=2nfi−1fn−i+∑i=2nfi−2fn−i
=
f
0
f
n
+
f
1
f
n
−
1
+
∑
i
=
1
n
f
i
f
n
−
i
−
1
+
∑
i
=
0
n
f
i
f
n
−
i
−
2
\ \ \ \ \ \ =f_0f_n+f_1f_{n-1}+\sum_{i=1}^n{f_{i}f_{n-i-1}}+\sum_{i=0}^{n}{f_{i}f_{n-i-2}}
=f0fn+f1fn−1+∑i=1nfifn−i−1+∑i=0nfifn−i−2
=
f
0
f
n
+
f
1
f
n
−
1
+
∑
i
=
0
n
f
i
f
n
−
i
−
1
−
f
0
f
n
−
i
+
∑
i
=
2
n
f
i
−
2
f
n
−
i
\ \ \ \ \ \ =f_0f_n+f_1f_{n-1}+\sum_{i=0}^n{f_{i}f_{n-i-1}}-f_0f_{n-i}+\sum_{i=2}^{n}{f_{i-2}f_{n-i}}
=f0fn+f1fn−1+∑i=0nfifn−i−1−f0fn−i+∑i=2nfi−2fn−i
=
f
0
f
n
+
∑
i
=
0
n
f
i
f
n
−
i
−
1
+
∑
i
=
2
n
f
i
−
2
f
n
−
i
\ \ \ \ \ \ =f_0f_n+\sum_{i=0}^n{f_{i}f_{n-i-1}}+\sum_{i=2}^{n}{f_{i-2}f_{n-i}}
=f0fn+∑i=0nfifn−i−1+∑i=2nfi−2fn−i
=
F
n
−
1
+
F
n
−
2
+
f
n
\ \ \ \ \ \ =F_{n-1}+F_{n-2}+f_n
=Fn−1+Fn−2+fn
然后用矩阵快速幂实现即可:
(
f
n
f
n
+
1
F
n
F
n
+
1
∑
i
=
0
n
F
)
=
(
0
1
0
0
0
1
1
0
0
0
0
0
0
1
0
1
1
1
1
0
0
0
0
1
1
)
×
(
f
n
−
1
f
n
F
n
−
1
F
n
∑
i
=
0
n
−
1
F
)
=
(
0
1
0
0
0
1
1
0
0
0
0
0
0
1
0
1
1
1
1
0
0
0
0
1
1
)
n
×
(
1
1
1
2
1
)
\begin{pmatrix} f_n \\ f_{n+1} \\ F_n \\ F_{n+1}\\ \sum_{i=0}^nF\\ \end{pmatrix}= \begin{pmatrix} 0&1&0&0&0\\ 1&1&0&0&0\\ 0&0&0&1&0\\ 1&1&1&1&0\\ 0&0&0&1&1\\ \end{pmatrix}\times \begin{pmatrix} f_{n-1} \\ f_{n} \\ F_{n-1} \\ F_{n}\\ \sum_{i=0}^{n-1}F\\ \end{pmatrix}= \begin{pmatrix} 0&1&0&0&0\\ 1&1&0&0&0\\ 0&0&0&1&0\\ 1&1&1&1&0\\ 0&0&0&1&1\\ \end{pmatrix}^{n}\times \begin{pmatrix} 1\\ 1\\ 1\\ 2\\ 1\\ \end{pmatrix}
⎝⎜⎜⎜⎜⎛fnfn+1FnFn+1∑i=0nF⎠⎟⎟⎟⎟⎞=⎝⎜⎜⎜⎜⎛0101011010000100011100001⎠⎟⎟⎟⎟⎞×⎝⎜⎜⎜⎜⎛fn−1fnFn−1Fn∑i=0n−1F⎠⎟⎟⎟⎟⎞=⎝⎜⎜⎜⎜⎛0101011010000100011100001⎠⎟⎟⎟⎟⎞n×⎝⎜⎜⎜⎜⎛11121⎠⎟⎟⎟⎟⎞
代码实现如下:
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int mod=998244353;
struct maxtri
{
ll a[10][10];
maxtri() {memset(a,0,sizeof(a));}
void build()
{
for(int i=1;i<=5;++i)
a[i][i]=1;
}
};
maxtri operator *(const maxtri &x,const maxtri &y)
{
maxtri res;
for(int k=1;k<=5;++k)
for(int i=1;i<=5;++i) if(x.a[i][k]!=0)
for(int j=1;j<=5;++j)
res.a[i][j]=(res.a[i][j]+x.a[i][k]*y.a[k][j]%mod)%mod;
return res;
}
maxtri fpow(maxtri a,ll k)
{
maxtri res; res.build();
while(k)
{
if(k&1) res=res*a;
a=a*a;
k>>=1;
}
return res;
}
int main()
{
// freopen("input.txt","r",stdin);
ll n; scanf("%lld",&n);
maxtri ans,base;
ans.a[1][1]=1; ans.a[2][1]=1; ans.a[3][1]=1; ans.a[4][1]=2; ans.a[5][1]=1;
base.a[1][2]=base.a[2][1]=base.a[2][2]=base.a[3][4]=base.a[4][1]=base.a[4][2]=base.a[4][3]=base.a[4][4]=base.a[5][4]=base.a[5][5]=1;
ans=fpow(base,n)*ans;
printf("%lld",ans.a[5][1]);
return 0;
}