HDU 6470 Count(矩陣快速冪)

題意:

第一頭牛和第二頭牛的號碼爲 1 和 2,其餘的牛的號碼需要通過公式求得:

f(n) = f(n - 1) + 2 * f(n - 2) + n * n * n , (f(1) = 1,f(2) = 2,分別是第一頭和第二頭)。

題解:

與前幾項有關的加法公式一般都是用矩陣快速冪來解的。。。所以解法就是矩陣快速冪。

很明顯,右矩陣肯定與 f(n - 1)、f(n - 2) 和 n * n * n。

問題來了,怎麼把 n * n * n 轉移爲 (n + 1) * (n + 1) * (n + 1)?直接算。。。可以得到 :

n * n * n + 3 * n * n - 3 * n + 1 = (n + 1) * (n + 1) * (n + 1),所以我們還要有 n * n 、 n 和 1,同理可以得到:

n * n  + 2 * n + 1 = (n + 1) * (n + 1)。

所以右矩陣就這麼可以得出來了:

\begin{bmatrix}f(n-1) \\ f(n-2) \\ n^{3} \\ n^{2} \\ n \\1 \end{bmatrix}

左矩陣根據關係可以得:

\begin{bmatrix} 1 & 2 & 1 & 0 & 0 & 0\\ 1 & 0 & 0 & 0 & 0 & 0\\ 0 & 0 & 1 & 3 & -3 & 1\\ 0 & 0 & 0 & 1 & 2 & 1\\ 0 & 0 & 0 & 0 & 1 & 1\\ 0 & 0 & 0 & 0 & 0 & 1 \end{bmatrix}

推出來就可以直接對左矩陣快速冪,直接輸出。

AC代碼:

#include <algorithm>
#include  <iostream>
#include   <cstdlib>
#include   <cstring>
#include    <cstdio>
#include    <string>
#include    <vector>
#include    <bitset>
#include     <stack>
#include     <cmath>
#include     <deque>
#include     <queue>
#include      <list>
#include       <set>
#include       <map>
#pragma comment(linker, "/STACK:1024000000,1024000000")
#define line printf("---------------------------\n")
#define mem(a, b) memset(a, b, sizeof(a))
#define pi acos(-1)
using namespace std;
typedef long long ll;
const double eps = 1e-9;
const int inf = 0x3f3f3f3f;
const int mod = 123456789;
const int maxn = 2000+10;

struct node {
	ll mrx[6][6];
	node(){}
	node(ll mapp[6][6]) {
		for(int i = 0; i < 6; i++) {
			for(int j = 0; j < 6; j++) {
				mrx[i][j] = mapp[i][j];
			}
		}
	}
	node(ll x) {
		for(int i = 0; i < 6; i++) {
			for(int j = 0; j < 6; j++) {
				if(i == j) {
					mrx[i][j] = x;
				} else {
					mrx[i][j] = 0;
				} 
			}
		}
	}
	friend node operator * (node a, node b) {
		node ans;
		for(int i = 0; i < 6; i++) {
			for(int j = 0; j < 6; j++) {
				ll p = 0;
				for(int k = 0; k < 6; k++) {
					p = (p + (a.mrx[i][k] * b.mrx[k][j]) % mod) % mod;
				}
				ans.mrx[i][j] = p;
			}
		}
		return ans;
	}
	void print() {
		for(int i = 0; i < 6; i++) {
			for(int j = 0; j < 6; j++) {
				cout << mrx[i][j] << " ";
			}
			cout << endl;
		}
	}
};

node qpow(node a, ll b) {
	node sum(1);
	while(b) {
		if(b & 1) {
			sum = sum * a;
		}
		a = a * a;
		b >>= 1;
	}
	return sum;
}

int main() {
	ll mapp[6][6] = {{1,2,1,0,0,0},
					  {1,0,0,0,0,0},
				   	  {0,0,1,3,-3,1},
					  {0,0,0,1,2,1},
					  {0,0,0,0,1,1},
					  {0,0,0,0,0,1}};
	node temp(mapp);
	int t;
	cin >> t;
	while(t--) {
		ll n;
		cin >> n;
		node m = qpow(temp, n - 2);
		ll ans[6] = {2,1,27,16,4,1};
		for(int i = 0; i < 6; i++) {
			ll sum = 0;
			for(int j = 0; j < 6; j++) {
				sum = (sum + (ans[j] * m.mrx[i][j]) % mod) % mod;
			}
			ans[i] = sum;
		}
		cout << ans[0] << endl;
	}
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章