【SSL 例5】前n項的和【矩陣乘法】
技術標籤:SSLOnlineJudge數論矩陣乘法
題目描述:
數列
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]的快速求法
對
9973
9973
9973取
m
o
d
mod
mod
(
(
(不考慮高精度
)
)
)
樣例:
i n p u t input input 1 : 1: 1:
100
o u t p u t output output 1 : 1: 1:
2528
i n p u t input input 2 : 2: 2:
1234567
o u t p u t output output 2 : 2: 2:
9860
分析:
矩陣乘法
.
.
.
考慮一個
1
∗
5
1*5
1∗5的矩陣
A
[
f
n
−
2
,
f
n
−
1
,
s
n
−
2
,
n
,
1
]
A[f_{n-2},f_{n-1},s_{n-2},n,1]
A[fn−2,fn−1,sn−2,n,1]
我們要找到一個矩陣
B
B
B 使得
:
:
:
[
f
n
−
1
,
f
n
,
s
n
−
1
,
n
+
1
,
1
]
=
[
f
n
−
1
,
f
n
−
2
+
f
n
−
1
+
n
+
1
,
s
n
−
2
+
f
n
−
1
,
n
+
1
,
1
]
[f_{n-1},f_{n},s_{n-1},n+1,1]=[f_{n-1},f_{n-2}+f_{n-1}+n+1,s_{n-2}+f_{n-1},n+1,1]
可以構造出
B
B
B為:
s
s
s就在
m
a
t
r
i
x
[
1
]
[
3
]
matrix[1][3]
matrix[1][3]
CODE:
#include<algorithm>
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
const int mod=9973;
long long n;
using namespace std;
struct matrix{
int n,m;
int F[11][11];
}A,B,C;
matrix operator *(matrix A,matrix B){
matrix C;
C.n=A.n,C.m=B.m;
for(int i=1;i<=C.n;i++)
for(int j=1;j<=C.m;j++)
C.F[i][j]=0;
for(int k=1;k<=A.m;k++)
for(int i=1;i<=C.n;i++)
for(int j=1;j<=C.m;j++)
C.F[i][j]=(C.F[i][j]+(A.F[i][k]*B.F[k][j])%mod)%mod; //矩陣乘法
return C;
}
void ksm(long long x){
if(x==1){
B=A;
return;
}
ksm(x>>1);
B=B*B;
if(x&1) B=B*A;
}
int main(){
scanf("%lld",&n);
if(n==1){
printf("1");
return 0;
}
A.n=5,A.m=5;
A.F[1][1]=0,A.F[1][2]=1,A.F[1][3]=0,A.F[1][4]=0,A.F[1][5]=0;
A.F[2][1]=1,A.F[2][2]=1,A.F[2][3]=1,A.F[2][4]=0,A.F[2][5]=0;
A.F[3][1]=0,A.F[3][2]=0,A.F[3][3]=1,A.F[3][4]=0,A.F[3][5]=0;
A.F[4][1]=0,A.F[4][2]=1,A.F[4][3]=0,A.F[4][4]=1,A.F[4][5]=0; //變換矩陣
A.F[5][1]=0,A.F[5][2]=1,A.F[5][3]=0,A.F[5][4]=1,A.F[5][5]=1;
ksm(n-1);
C.n=1,C.m=5;
C.F[1][1]=1,C.F[1][2]=1,C.F[1][3]=1,C.F[1][4]=3,C.F[1][5]=1; //初始
C=C*B;
printf("%d",C.F[1][3]);
return 0;
}