代码改变世界

模板 n维矩阵的二分幂

2012-03-23 15:43  javaspring  阅读(195)  评论(0编辑  收藏  举报

      今天一上午一下午就干了点这,就写了一个这样恶心的模板,,写出来我自己都不想看,,不过还好,可以用。。这个模板可以求n维矩阵的二分幂,主要适用于递推式求值的题目。。

代码:

#include <iostream>
#include <cstdio>
#include <string.h>
using namespace std;
typedef long long ll;
const ll MAX=1000007;
const int row=3;//矩阵的维数,根据题目要求改变
ll aa[11][11],bb[11][11];//aa,bb存储矩阵
ll cc[11][11];//结果矩阵
ll dd[11][11];//单位矩阵
ll mi;//多少次方
class matrix{
public:
	void input(ll f[11],ll num[11]);
	void initmatrix(ll p[11],ll q[11]);
	void matrixmi(int x);//矩阵幂
	void matrixfun(ll a[11][11],ll b[11][11]);//矩阵乘积
};
void matrix::input(ll f[11],ll num[11]){
  	//输入前几项
	for(int i=1;i<row;++i){
	  scanf("%lld",&f[i]);
	}
	//输入前几项对应的系数
	for(int i=1;i<=row;++i){
	  scanf("%lld",&num[i]);
	}
	//输入所求的n次方
	scanf("%lld",&mi);
}
//构造矩阵
void matrix::initmatrix(ll ff[11],ll a[11]){
   memset(aa,0,sizeof(aa));
   memset(bb,0,sizeof(bb));
   //构造单位矩阵
   for(int i=1;i<=row;++i){
     for(int j=1;j<=row;++j)
		 dd[i][j]=0;
	 dd[i][i]=1;
   }
    for(int i=1;i<row;++i)
	   aa[1][i]=ff[i];
   aa[1][row]=a[row];//原矩阵
   for(int i=1;i<=row-2;++i)
	   bb[i+1][i]=1;
   bb[row][row]=1;bb[row][row-1]=1;
   for(int i=1;i<row;++i)
     bb[i][row-1]=a[i];//构造所要乘的矩阵
}
//矩阵乘法
void matrix::matrixfun(ll a[11][11],ll b[11][11]){
  long long sum=0;
  memset(cc,0,sizeof(cc));
  for(int i=1;i<=row;++i){
	  for(int j=1;j<=row;++j){
	    sum=0;
		for(int k=1;k<=row;++k)
			sum+=(a[i][k]*b[k][j]);
		cc[i][j]=(sum%MAX);
	  }
  }
}
//矩阵二分幂
void matrix::matrixmi(int x){
	while(x){
		if(x&1){
		  matrixfun(dd,bb);
		  for(int i=1;i<=row;++i)
			  for(int j=1;j<=row;++j)
				  dd[i][j]=cc[i][j];
		}
		matrixfun(bb,bb);
		for(int i=1;i<=row;++i)
			for(int j=1;j<=row;++j)
				bb[i][j]=cc[i][j];
		x=x>>1;
	}
	matrixfun(aa,dd);
}
int main(){
  int numcase;
  scanf("%d",&numcase);
  while(numcase--){
    matrix mm;
	ll f[11],num[11];
	mm.input(f,num);
	if(mi<row){
	  cc[1][row-1]=f[mi]%MAX;
	}
	else{
	  mm.initmatrix(f,num);
	  mm.matrixmi(mi-2);
	}
	if(cc[1][row-1]>0)
	printf("%lld\n",cc[1][row-1]);
	else
		printf("%lld\n",cc[1][row-1]+MAX);
  }
  return 0;
}