题目描述
数列 f [ n ] = f [ n − 1 ] + f [ n − 2 ] + n + 1 , f [ 1 ] = f [ 2 ] = 1 f[n]=f[n-1]+f[n-2]+n+1,f[1]=f[2]=1 f[n]=f[n−1]+f[n−2]+n+1,f[1]=f[2]=1的前 n n n项和 s [ n ] s[n] s[n]的快速求法
思路:
考虑矩阵乘法
将
[
f
n
−
1
f
n
−
2
s
n
−
2
n
1
]
\begin{bmatrix}f_{n-1} & f_{n-2} & s_{n-2} & n & 1\end{bmatrix}
[fn−1fn−2sn−2n1]转为
[
f
n
f
n
−
1
s
n
−
1
n
+
1
1
]
\begin{bmatrix}f_{n} & f_{n-1} & s_{n-1} & n+1 & 1\end{bmatrix}
[fnfn−1sn−1n+11],可以推出转移矩阵
[
1
1
1
0
0
1
0
0
0
0
0
0
1
0
0
1
0
0
1
0
1
0
0
1
1
]
\begin{bmatrix}1 & 1 & 1 & 0 & 0\\1 & 0 & 0 & 0 & 0\\0 & 0 & 1 & 0 & 0\\1 & 0 & 0 & 1 & 0\\1 & 0 & 0 & 1 & 1\end{bmatrix}
⎣⎢⎢⎢⎢⎡1101110000101000001100001⎦⎥⎥⎥⎥⎤
code:
#include<iostream>
#include<cstdio>
using namespace std;
int n;
int a[10][10];
int ans[10][10];
int p=9973;
void multi()
{
int c[10][10];
for(int i=1; i<=5; i++)
for(int j=1; j<=5; j++)
c[i][j]=0;
for(int i=1; i<=5; i++)
for(int j=1; j<=5; j++)
for(int k=1; k<=5; k++)
c[i][j]=(c[i][j]+ans[i][k]*a[k][j])%p;
for(int i=1; i<=5; i++)
for(int j=1; j<=5; j++)
ans[i][j]=c[i][j];
}
void multi1()
{
int c[10][10];
for(int i=1; i<=5; i++)
for(int j=1; j<=5; j++)
c[i][j]=0;
for(int i=1; i<=5; i++)
for(int j=1; j<=5; j++)
for(int k=1; k<=5; k++)
c[i][j]=(c[i][j]+a[i][k]*a[k][j])%p;
for(int i=1; i<=5; i++)
for(int j=1; j<=5; j++)
a[i][j]=c[i][j];
}
void ksm(int k)
{
ans[1][1]=ans[2][2]=ans[3][3]=ans[4][4]=ans[5][5]=1;
while(k!=0)
{
if(k&1)
multi();
multi1();
k>>=1;
}
}
void multi2()
{
int c[10][10];
for(int i=1; i<=1; i++)
for(int j=1; j<=5; j++)
c[i][j]=0;
for(int i=1; i<=1; i++)
for(int j=1; j<=5; j++)
for(int k=1; k<=5; k++)
c[i][j]=(c[i][j]+a[i][k]*ans[k][j])%p;
for(int i=1; i<=1; i++)
for(int j=1; j<=5; j++)
ans[i][j]=c[i][j];
}
int main()
{
scanf("%d", &n);
a[1][1]=a[2][1]=a[4][1]=a[5][1]=1;
a[1][2]=1;
a[1][3]=a[3][3]=1;
a[4][4]=a[5][4]=1;
a[5][5]=1;
ksm(n-2);
a[1][1]=a[1][2]=1;
a[1][3]=1;
a[1][4]=3;
a[1][5]=1;
multi2();
printf("%d", (ans[1][1]+ans[1][3])%p);
return 0;
}