1. 程式人生 > >hdu 1005(矩陣快速冪)

hdu 1005(矩陣快速冪)

題目傳送門

題目描述的是一個遞推,並且沒有其他變數與n有關,是一個典型的矩陣快速冪模板題(有多種解法,只提這一種)。

{1,1} * A{A,1}   = {f(n),f(n-1)}

             {B,0}

/**
矩陣快速冪 模板 
**/
#include <algorithm>
#include  <iostream>
#include   <cstring>
#include    <string>
#include    <vector>
#include     <cmath> 
#include     <deque>
#include       <map>


#define For(i,a,b) for(i = a;i < b;i ++)
#define For_(i,a,b) for(i = a;i > b; i --) 
#define Max 100
using namespace std;
typedef long long ll;
int Nnum;//矩陣的大小 ,預設為 Nnum * Nnum,這樣很好計算 ,從零開始 
int Mod = 7;//取模的大小 
typedef struct node{//Array 在前,* 的在後 
	ll Array[Max][Max];
	node operator * (node a){
		int i,j,k;
		node ans;
		For(i,0,Nnum+1){
			For(j,0,Nnum+1){
				ans.Array[i][j] = 0;
			}
		}
		For(k,0,Nnum +1){//k 在外面可以剪枝 0 的運算 
			For(i,0,Nnum +1){
				if(Array[i][k] != 0)
				For(j,0,Nnum +1){
					if(a.Array[k][j] != 0){
						ans.Array[i][j] =(ans.Array[i][j] + Array [i][k] * a.Array[k][j] % Mod) % Mod;
					}
				}
			}
		}
		return ans;
	}
	
}Node;

void Print(node a){ // 輸出 矩陣 
	int i,j;
	For(i,0,Nnum+1){
		For(j,0,Nnum+1){
			cout<<a.Array[i][j]<<" ";
		}
		cout<<endl;
	}
} 

node Clear(){// 矩陣 初始化
	node a;
	int i,j,k;
	For(i,0,Nnum+1){
		For(j,0,Nnum+1){
			a.Array[i][j] = (i == j);
		}
	}
	return a; 
}

node ArrayQuit(node ans,node a,int N){//快速冪 
	while(N){
		if(N & 1)ans = (ans * a);
		a = (a * a);
		N >>= 1;
		
	} 
	return ans;
} 

/*
1 1 3
1 2 10
0 0 0
 
*/
int main(){
	Nnum = 9;//初始化 Nnum Nnum 是矩陣的規模 
	int i,j,k,n,a,b;
	node Array;
	while(scanf("%d%d%d",&a,&b,&n)==3){
		if(a==0&&b==0&&n==0)break;
		if(n < 3){
			printf("1\n");
			continue;
		}
		Array.Array[0][0] = a,Array.Array[0][1] = 1,Array.Array[1][0] = b,Array.Array[1][1]= 0;
		node ans;
		ans.Array[0][0]=1,ans.Array[0][1] = 1; 
//		Print(ans);
		ans = ArrayQuit(ans,Array,n-2);
//		cout<<"ans:\n";
//		Print(ans);
		printf("%d\n",ans.Array[0][0]);
	}
	
	return 0;
}