您的位置:首页 > 其它

51 nod 1242 斐波那契数列的第N项 矩阵快速幂

2017-08-28 20:30 429 查看
传送门51 nod 1242




Input示例
11

Output示例
89




题意:中文题,一般人都应该能看懂吧……

注意:注意n的范围,我这道题WA了N次,就是因为n的范围,n最大是10^18,所以得用龙龙(long long)型。

前置技能:矩阵快速幂。矩阵快速幂和整数快速幂的思想一致,只是把整数乘法改为了矩阵乘法,整数中的单位元1改为了矩阵中的单位矩阵。

思路:最直接的想法肯定是直接利用斐波那契数列的递推公式求解了,但是n太大了,会超时。正确的姿势是采用矩阵快速幂求解的方式。我们要构造一个2 x 2的矩阵,使得它乘以(a,b)得到的结果是(a+b,b),分别是前两项之和和第二项的值。每多乘一次这个矩阵,这两个数就会多迭代一次。那么,我们把这个矩阵自乘n-1次(因为乘以的是(0,1),即斐波那契数列的第0和第1项的值,乘以一次得第2项的值),再乘以(0,1)就可以得到第n个Fibonacci数了。易知这个矩阵是:   

                                       1 1          

                                       1 0

进行n-1次自乘后,第0行第0列的值就是第n项斐波那契数列的值。

具体实现:先初始化2x2的矩阵和单位矩阵,然后调用矩阵快速幂,结果矩阵的第0行第0列就是结果。

顺便附上Matrix67的关于矩阵快速幂应用的十个经典题目网址。

//n的值要用long long型
#include<stdio.h>
typedef long long LL;

int m=1000000009; //m为要取模的数

struct matrix
{
LL map[10][10];
}a,per; //a是要自乘的2*2的矩阵,per是2*2的单位矩阵

void init()
{ //初始化函数
a.map[0][0]=1;
a.map[0][1]=1;
a.map[1][0]=1;
a.map[1][1]=0;
int i,j;
for(i=0;i<2;i++) //单位矩阵对角线为1,其他为0
for(j=0;j<2;j++)
per.map[i][j]=(i==j);
}

matrix multi(matrix a,matrix b)
{ //两个矩阵a、b相乘
matrix c;
int i,j,k;
for(i=0;i<2;i++)
for(j=0;j<2;j++)
{
c.map[i][j]=0;
for(k=0;k<2;k++) c.map[i][j]+=(a.map[i][k]*b.map[k][j])%m;
c.map[i][j]%=m;
}
return c;
}

matrix power(LL k)
{ //矩阵快速幂
matrix p,ans;
ans=per;
p=a;
while(k)
{
if(k&1) ans=multi(ans,p);
p=multi(p,p);
k/=2;
}
return ans;
}

int main()
{
int i;
LL n;
matrix ans;
while(~scanf("%lld",&n))
{
init();
ans=power(n-1);
printf("%lld\n",ans.map[0][0]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: