「Spoj SEQ」 Recursive Sequence

Description

Defines the number of columns \ (A \) of \ (I \) term \ (a_i \) of the formula:

\(\begin{cases} a_i = b_i & i \le k \\ a_i = \sum\limits_{t=1}^k a_{i-t} \times c_{t} & i > k \end{cases}\)

Now given \ (k, b = \ {b_1, b_2, \ cdots, b_k \}, c = \ {c_1, c_2, \ cdots, c_k \}, n \) , find \ (a_n \ bmod 10 ^ 9 \) .

Hint

\ (1 \ and k \ le 10 \)

\ (1 \ le n \ le 10 ^ 9 \)

\ (0 \ le b_i, c_i \ le 10 ^ 9 \)

Solution

Good matrix optimization recursive \ (k \) item recursive board. No constant term is even simpler.

First, for the case of \ (n \ le k \) , directly output the value of \ (b_n \) .

For the case of \ (n> k \) , matrix acceleration is required.

\[\begin{bmatrix} a_i \\ a_{i-1} \\ \vdots \\ a_{i-k} \end{bmatrix} = \begin{bmatrix} c_1 & \cdots & c_{k-1} & c_k \\ 1 & \cdots & 0 & 0 \\ \vdots & \ddots & \vdots & \vdots \\ 0 & \cdots & 1 & 0 \end{bmatrix} \times \begin{bmatrix} a_{i-1} \\ a_{i-2} \\ \vdots \\ a_{i-k-1} \end{bmatrix} \]

The formula for this kind of problem is almost the same: the top row of coefficients, and the diagonally put 1 below.

How to understand this formula?

The \ (a_i \) term of the new matrix is obtained by multiplying all the elements in the old matrix by the sum of the coefficients, and the other elements of the new matrix can be directly taken from the elements of the old matrix and moved down by one bit.

Code

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

const int mod = 1e9;
typedef long long LL;
typedef vector<LL> vec;
typedef vector<vec> mat;

inline mat operator * (mat a,mat b) {
	mat x(a.size(), vec(b[0].size(), 0));
	for (register int i = 0; i < a.size(); i++)
		for (register int j = 0; j < b[0].size(); j++)
			for (register int k = 0; k < b.size(); k++)
				(x[i][j] += a[i][k] * b[k][j]) %= mod;
	return x;
}

inline mat matI(int n) {
	mat x(n, vec(n, 0));
	for (register int i = 0; i < n; i++)
		x[i][i] = 1;
	return x;
}

mat fastpow(mat base, int k) {
	if (!k) return matI(base.size());
	mat x = fastpow(base, k >> 1);
	if (k & 1) return (x * x) * base;
	else return x * x;
}

void solve() {
	int n, k;
	cin >> k;
	mat b(k, vec(1, 0)), c(k, vec(1, 0));
	for (register int i = 0; i < k; i++)
		cin >> b[i][0];
	for (register int i = 0; i < k; i++)
		cin >> c[i][0];
	cin >> n;
	
	if (n <= k) cout << b[n - 1][0] << endl;
	else {
		mat base(k, vec(k, 0));
		for (register int i = 0; i < k; i++)
			base[0][i] = c[i][0];
		for (register int i = 1; i < k; i++)
			base[i][i - 1] = 1;
		reverse(b.begin(), b.end());
		b = fastpow(base, n - k) * b;
		cout << b[0][0] << endl;
	}
}

signed main() {
	int T;
	cin >> T;
	while (T--)	solve();
	return 0;
}

Guess you like

Origin www.cnblogs.com/-Wallace-/p/12671912.html