[数论]矩阵快速幂

/*
Name:BjfuOJ1440 (矩阵快速幂)

Actor:HT

Time:2015年10月9日

Error Reporte:	1.求模运算,一定要有最后一次!

*/

#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define N 1010
#define G 1000000007

using namespace std;

//矩阵快速幂的作用是通过构造矩阵乘法,
//使将 递推公式 优化成 幂算式
//继而通过快速幂完成运算
//O(n) -> O(logn)

//本题递推 f(n) = 2 * (f(n-1) + f(n-2))
//f1 = 3	f2 = 8

struct mat
{
	__int64 a11;__int64 a12;
	__int64 a21;__int64 a22;
};

mat ht;

void matmlt(mat& ma, mat mb)	//4*4矩阵乘法 赋值给ma
{
	mat temp = ma;
	ma.a11 = temp.a11 * mb.a11 % G + temp.a12 * mb.a21 % G;
	ma.a12 = temp.a11 * mb.a12 % G + temp.a12 * mb.a22 % G;
	ma.a21 = temp.a21 * mb.a11 % G + temp.a22 * mb.a21 % G;
	ma.a22 = temp.a21 * mb.a12 % G + temp.a22 * mb.a22 % G;
}

mat matpow(mat a,__int64 n)	//矩阵快速幂
{
	mat answ;
	answ.a11 = 1;
	answ.a12 = 0;
	answ.a21 = 0;
	answ.a22 = 1;
	for (; n > 1;)
	{
		if (n % 2 == 1)
			matmlt(answ, a);
		n /= 2;
		matmlt(a,a);
	}
	matmlt(answ,a);
	return answ;
}

__int64 fun(__int64 x)
{
	mat	temp = matpow(ht, x-2);
	return (temp.a11 * 8 % G + temp.a12 * 3 % G)%G;	//	BUG点 别忘了最后再求次模!
}

void pre()
{
	ht.a11 = 2;
	ht.a12 = 2;
	ht.a21 = 1;
	ht.a22 = 0;
}

int main()
{
	int t, i, j, k;
	__int64 temp,n;
	pre();
	while (scanf("%I64d", &n) != EOF)
	{
		if (n > 2)
		{
			temp = fun(n);
			printf("%I64d\n", temp);
		}
		else if (n == 2)
			printf("8\n");
		else if (n == 1)
			printf("3\n");
	}
	return 0;
}

//本体示意如下:  (矩阵构造因题而异)
//  2 2	*	f2	=	f3
//  1 0		f1		f2

//本题中出现很多愚蠢初始化,是因为OJ编译器问题

你可能感兴趣的:(算法与结构)