Time Limit:1000MS Memory Limit:65536K
Total Submit:124 Accepted:52
Description
形如 1 1 2 3 5 8 13 21 34 55 89 144…的数列,求裴波拉契数列的第n项。
Input
n ( 1 < n < 2 3 1 ) n (1< n <2^31) n(1<n<231)
Output
一个数为裴波拉契数列的第 n n n项 m o d 10000 mod 10000 mod10000;
Sample Input
123456789
Sample Output
4514
Source
elba
解题思路
考虑1×2的矩阵
【
f
[
n
−
2
]
,
f
[
n
−
1
]
】
【f[n-2],f[n-1]】
【f[n−2],f[n−1]】。根据fibonacci数列的递推关系,我们希望通过乘以一个
2
×
2
2×2
2×2的矩阵,得到矩阵
【
f
[
n
−
1
]
,
f
[
n
]
】
=
【
f
[
n
−
1
]
,
f
[
n
−
1
]
+
f
[
n
−
2
]
】
【f[n-1],f[n]】=【f[n-1],f[n-1]+f[n-2]】
【f[n−1],f[n]】=【f[n−1],f[n−1]+f[n−2]】很容易构造出这个
2
×
2
2×2
2×2矩阵
A
A
A,即:
所以,有
【
f
[
1
]
,
f
[
2
]
】
×
A
=
【
f
[
2
]
,
f
[
3
]
】
【f[1],f[2]】×A=【f[2],f[3]】
【f[1],f[2]】×A=【f[2],f[3]】
又因为矩阵乘法满足结合律,故有:
【
f
[
1
]
,
f
[
2
]
】
×
A
n
−
1
=
【
f
[
n
]
,
f
[
n
+
1
]
】
【f[1],f[2]】×A n-1=【f[n],f[n+1]】
【f[1],f[2]】×An−1=【f[n],f[n+1]】
这个矩阵的第一个元素即为所求。
代码
#include<algorithm>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
const int INF=10000;
long long n;
using namespace std;
struct c{
int n,m;
int a[10][10];
}A,B,CC;
c operator *(c A,c B){
c 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.a[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.a[i][j]=(C.a[i][j]+(A.a[i][k]*B.a[k][j])%INF)%INF;
}
return C;
}
void poww(long long x){
if(x==1)
{
B=A;
return;
}
poww(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=2,A.m=2;
A.a[1][1]=0,A.a[1][2]=1,A.a[2][1]=1,A.a[2][2]=1;
poww(n-1);
CC.n=1,CC.m=2;
CC.a[1][1]=1,CC.a[1][2]=1;
CC=CC*B;
printf("%d\n",CC.a[1][1]);
}