1. 程式人生 > >Recursive sequence HDU

Recursive sequence HDU

題幹就不說了,直接上分析。

此題的遞推公式為 f [ n ] = f [ n - 1 ] + 2 * f [ n - 2 ] + n ^ 4,難點就在於構造轉移矩陣,轉移矩陣構造出來整個題目也就解決了,當然還要注意如果題目給的n小於3,直接輸出就好了(在這個點栽了一發。。)

構造轉移矩陣的難點在於如何處理n的四次方這一部分。

在此提供一個方法,凡是有n次冪的時候基本上都可以用。

因為要保持形式一致,我們要考慮如何將(n + 1)^4和n^4聯絡起來。

得到:(n + 1) ^ 4 = n^4 + 4 * n^3 + 6 * n^2 + 4 * n + 1;

請注意:這裡面還存在著n^3, n^2, n, 1。因為轉移矩陣中只能是一些常數,所以我們把所需要的變數因子都單列出來,就像這樣:

f[n - 1]

f[n - 2]

n^4

n^3

n^2

n

1

然後只需要每一項乘上相應的常數係數轉移過去就好了,完整的矩陣如下:

f[n]                       1 2 1 0 0 0 0             f[n - 1] f[n - 1]                  1 0 0 0 0 0 0            f[n - 2] (n + 1)^4             0 0 1 4 6 4 1             n^4 (n + 1)^3             0 0 0 1 3 3 1             n^3 (n + 1)^2             0 0 0 0 1 2 1             n^2 (n + 1)                 0 0 0 0 0 1 1             n 1                          0 0 0 0 0 0 1             1

最後只需要套個矩陣快速冪的模板就好了

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>

using namespace std;

typedef long long ll;
int t, n, a, b;
ll mod = 2147493647;
struct Matrix
{
	ll mat[15][15];
	Matrix()
	{
		memset(mat, 0, sizeof(mat));
	}
	friend Matrix operator * (Matrix A, Matrix B)
	{
		Matrix ans;
		for(int i = 1; i <= 7; ++ i)
		{
			for(int j = 1; j <= 7; ++ j)
			{
				for(int k = 1; k <= 7; ++ k)
				{
					ans.mat[i][j] += (A.mat[i][k] * B.mat[k][j]) % mod;
					ans.mat[i][j] %= mod;
				}
			}
		}
		return ans;
	}
};


Matrix quick_matrix(Matrix A, int b)
{
	Matrix ans;
	for(int i = 1; i <= 7; ++ i)
	{
		ans.mat[i][i] = 1;
	}
	while(b)
	{
		if(b & 1)
		{
			ans = ans * A;
		}
		A = A * A;
		b >>= 1;
	}
	return ans;
}

int main()
{
	cin >> t;
	while(t--)
	{
		cin >> n >> a >> b;
		if(n == 1 || n == 2)
		{
			if(n == 1)
				cout << a << endl;
			else 
				cout << b << endl;
			continue;
		}
		Matrix A, B;
		A.mat[1][1] = b;
		A.mat[2][1] = a;
		A.mat[3][1] = 3 * 3 * 3 * 3;
		A.mat[4][1] = 3 * 3 * 3;
		A.mat[5][1] = 3 * 3;
		A.mat[6][1] = 3;
		A.mat[7][1] = 1;

		B.mat[1][1] = 1;
		B.mat[1][2] = 2;
		B.mat[1][3] = 1;

		B.mat[2][1] = 1;

		B.mat[3][3] = 1;
		B.mat[3][4] = 4;
		B.mat[3][5] = 6;
		B.mat[3][6] = 4;
		B.mat[3][7] = 1;

		B.mat[4][4] = 1;
		B.mat[4][5] = 3;
		B.mat[4][6] = 3;
		B.mat[4][7] = 1;

		B.mat[5][5] = 1;
		B.mat[5][6] = 2;
		B.mat[5][7] = 1;

		B.mat[6][6] = 1;
		B.mat[6][7] = 1;

		B.mat[7][7] = 1;
		B = quick_matrix(B, n - 2);
		A = B * A;
		cout << A.mat[1][1] << endl;
	}
	return 0;
}