Fibonacci poj-3070

    题目大意:求Fibonacci第n项。

    注释:模数为10000,$1\le n \le 10^9$。

      想法:矩阵题,用例题6的想法,我们构造矩阵

          $\begin{pmatrix} 0 & 1 \\ 1 & 1 \end{pmatrix}$

        然后,我们快速幂即可。

      附上lijinnn的版子

struct Matr
{
	int a[4][4];
	Matr(){memset(a,0,sizeof a);}
	Matr operator *(const Matr &z)
	{
		Matr re;
		int p=2;
		for(int i=0;i<p;++i)
		{
			for(int j=0;j<p;++j)
			{
				for(int k=0;k<p;++k)
				{
					re.a[i][j]=(re.a[i][j]+a[i][k]*z.a[k][j])%mod;
				}
			}
		}
		return re;
	}
};

      这是一种重载运算符的方式,我开始用的是函数。但是在快速幂的时候确实有些慢(如果直接传参的话)。感谢lijinnn(吉林队长)。

      其中,矩阵从零开始的空间优化特别多!此题没有...因为都没怎么开矩阵

    最后,附上丑陋的代码... ...

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cmath>
#define mod 10000 
using namespace std;
struct Matr
{
	int a[3][3];
	Matr(){memset(a,0,sizeof a);}
	Matr operator *(const Matr &z)//重定义运算符
	{
		Matr re;
		int p=2;
		for(int i=0;i<p;++i)
		{
			for(int j=0;j<p;++j)
			{
				for(int k=0;k<p;++k)
				{
					re.a[i][j]=(re.a[i][j]+a[i][k]*z.a[k][j])%mod;
				}
			}
		}
		return re;
	}
};
Matr quick_power(int x)//快速幂
{
	Matr ori;
	for(int i=0;i<=1;i++)
	{
		for(int j=0;j<=1;j++)
		{
			ori.a[i][i]=1;
		}
	}
	Matr k;
	k.a[0][1]=k.a[1][0]=k.a[1][1]=1;
	while(x)
	{
		if(x&1) ori=ori*k;
		k=k*k;
		x>>=1;
	}
	return ori;
}
int main()
{
	int n;
	while(1)
	{
		scanf("%d",&n);
		if(n==-1) return 0;
		Matr s;
		s=quick_power(n);
		Matr ans;
		ans.a[0][0]=-1;
		ans=ans*s;
		printf("%d\n",-ans.a[0][1]);//为了方便,我的初始矩阵用的是负数为的是如果求第i项,快速幂i次即可
		//但是由于开始是负数,所以需要在最后乘上-1
	}
}

    小结:矩阵好东西,推荐自己的blog 矩阵算法学习摘记