數列的三次方求前綴和(矩陣快速冪)

  • 難得一次推麻煩點的矩陣,矩陣快速冪以後要有信心推下去,暴力推就行了

  • 第一次用Markdown完整的寫完了一篇題解,這數學公式可真要命


題目描述:

  • 一個數列an{a_n},滿足an=xan1+yan2a_n = x * a_{n - 1} + y * a_{n - 2},求i=1nai3\sum^{n}_{i = 1} {a_i^3} 答案對998244353取模。

輸入

  • 第一行一個整數T,即數據組數。
  • 下面T行,每行5個整數,即n,a1,a2,x,y,含義如上。

輸出

  • 共T行,每行1個整數,即每組數據的答案。

樣例輸入

3
3 0 2 0 0
3 1 2 0 1
3 1 0 0 1

樣例輸出

8
10
2

提示

  • 對於100%的數據, 1T1041n10180a1a2xy9982443521≤T≤10^4,1≤n≤10^{18},0≤a_1,a_2,x,y≤998244352

題解:

就暴力拆開三次方 an3=x3an13+3x2yan12an2+3xy2an1an22+y3an23a_n^3 = x^3 a_{n-1}^3 + 3 x^2 y a_{n-1}^2 a_{n-2} + 3 x y ^ 2 a_{n - 1} a_{n - 2}^2 + y^3 a_{n-2}^3

然後用常用推矩陣的思路直接上4階基矩陣

base=(x33x2y3xy2y3x22xyy20xy001000)(1) base=\begin{pmatrix}x^3 & 3 x^2 y & 3 x y^2 & y^3\\x^2 & 2 x y & y^2 & 0\\x & y & 0 & 0\\1 & 0 & 0 & 0\end{pmatrix}\tag{1}


(an3an2an1anan12an13)=(x33x2y3xy2y3x22xyy20xy001000)(an13an12an2an1an22an23)(2) \begin{pmatrix}a_n^3 \\a_n^2 a_{n-1} \\a_n a_{n-1}^2 \\a_{n-1}^3\end{pmatrix}=\begin{pmatrix}x^3 & 3 x^2 y & 3 x y^2 & y^3\\x^2 & 2 x y & y^2 & 0\\x & y & 0 & 0\\1 & 0 & 0 & 0\end{pmatrix}\begin{pmatrix}a_{n-1}^3 \\a_{n-1}^2 a_{n-2} \\a_{n-1} a_{n-2}^2 \\a_{n-2}^3\end{pmatrix}\tag{2}

(an3an2an1anan12an13)=(x33x2y3xy2y3x22xyy20xy001000)n2(a23a22a1a2a12a13)(3) \begin{pmatrix}a_n^3 \\a_n^2 a_{n-1} \\a_n a_{n-1}^2 \\a_{n-1}^3\end{pmatrix}=\begin{pmatrix}x^3 & 3 x^2 y & 3 x y^2 & y^3\\x^2 & 2 x y & y^2 & 0\\x & y & 0 & 0\\1 & 0 & 0 & 0\end{pmatrix}^{n - 2}\begin{pmatrix}a_2^3 \\a_2^2 a_1 \\a_2 a_1^2 \\a_1^3\end{pmatrix}\tag{3}

那麼這個 an3a_n^3 就可以順利用矩陣快速冪推出來了

題目求的是i=1nai3\sum^{n}_{i = 1} {a_i^3},令Sn=i=1nai3S_n = \sum^{n}_{i = 1} {a_i^3}

那麼對基矩陣增加一行一列即可

base=(1x33x2y3xy2y30x33x2y3xy2y30x22xyy200xy0001000)(4) base=\begin{pmatrix}1 & x^3 & 3 x^2 y & 3 x y^2 & y^3 \\0 & x^3 & 3 x^2 y & 3 x y^2 & y^3 \\0 & x^2 & 2 x y & y^2 & 0 \\0 & x & y & 0 & 0 \\0 & 1 & 0 & 0 & 0\end{pmatrix}\tag{4}


(Snan3an2an1anan12an13)=(1x33x2y3xy2y30x33x2y3xy2y30x22xyy200xy0001000)(Sn1an13an12an2an1an22an23)(5) \begin{pmatrix}{S}_n \\a_n^3 \\a_n^2 a_{n-1} \\a_n a_{n-1}^2 \\a_{n-1}^3\end{pmatrix}= \begin{pmatrix}1 & x^3 & 3 x^2 y & 3 x y^2 & y^3 \\0 & x^3 & 3 x^2 y & 3 x y^2 & y^3\\0 & x^2 & 2 x y & y^2 & 0\\0 & x & y & 0 & 0\\0 & 1 & 0 & 0 & 0\end{pmatrix}\begin{pmatrix}S_{n-1} \\a_{n-1}^3 \\a_{n-1}^2 a_{n-2} \\a_{n-1} a_{n-2}^2 \\a_{n-2}^3\end{pmatrix}\tag{5}

(Snan3an2an1anan12an13)=(1x33x2y3xy2y30x33x2y3xy2y30x22xyy200xy0001000)n2(S2a23a22a1a2a12a13)(6) \begin{pmatrix}{S}_n \\a_n^3 \\a_n^2 a_{n-1} \\a_n a_{n-1}^2 \\a_{n-1}^3\end{pmatrix}= \begin{pmatrix}1 & x^3 & 3 x^2 y & 3 x y^2 & y^3 \\0 & x^3 & 3 x^2 y & 3 x y^2 & y^3\\0 & x^2 & 2 x y & y^2 & 0\\0 & x & y & 0 & 0\\0 & 1 & 0 & 0 & 0\end{pmatrix}^{n - 2}\begin{pmatrix}S_2 \\a_2^3 \\a_2^2 a_1 \\a_2 a_1^2 \\a_1^3\end{pmatrix}\tag{6}

#pragma GCC optimize(3, "Ofast", "inline")
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>

using namespace std;

typedef long long LL;

typedef unsigned long long uLL;

#define REP(i, a, b) for(register int i = (a), i##_end_ = (b); i <= i##_end_; ++ i)
#define DREP(i, a, b) for(register int i = (a), i##_end_ = (b); i >= i##_end_; -- i)
#define EREP(i, a) for(register int i = (be[a]); i != -1; i = nxt[i])
#define debug(...) fprintf(stderr, __VA_ARGS__)
#define mem(a, b) memset((a), b, sizeof(a))

template<typename T> inline bool chkmin(T &a, const T &b) { return a > b ? a = b, 1 : 0; }
template<typename T> inline bool chkmax(T &a, const T &b) { return a < b ? a = b, 1 : 0; }
template <class T>
T read(T sum = 0, T fg = 0)
{
	char c = getchar();
	while(c < '0' || c > '9') { fg |= c == '-'; c = getchar(); }
	while(c >= '0' && c <= '9') { sum = sum * 10 + c - '0'; c = getchar(); }
	return fg ? -sum : sum;
}

const int inf = 1e9;

const LL INF = 1e17;

const int Size = 1000010;

const LL mod = 998244353;

struct Matrix
{
	LL matrix[6][6];
	int lenx, leny;

	Matrix()
	{
		lenx = 5; leny = 5;
		mem(matrix, 0);
	}

	void base()
	{
		REP(i, 1, 5) matrix[i][i] = 1;
	}

	friend Matrix operator * (Matrix a, Matrix b)
	{
		Matrix res;
		res.lenx = a.lenx; res.leny = b.leny;
		REP(i, 1, res.lenx) REP(j, 1, res.leny) REP(k, 1, a.leny)
		{
			(res.matrix[i][j] += a.matrix[i][k] * b.matrix[k][j] % mod) %= mod;
		}
		return res;
	}
};

Matrix qpow(Matrix a, LL N)
{
	Matrix ans; ans.base();
	while(N)
	{
		if(N & 1LL) ans = ans * a;
		a = a * a;
		N >>= 1LL;
	}
	return ans;
}

LL calc(LL x, int k)
{
	LL ans = 1LL;
	while(k--) ans = ans * x % mod;
	return ans % mod;
}

void solve()
{
	LL n = read<LL>();
	LL a1 = read<LL>() % mod, a2 = read<LL>() % mod;
	LL x = read<LL>() % mod, y = read<LL>() % mod;

	if(n == 1)
	{
		printf("%lld\n", calc(a1, 3));
		return;
	}
	if(n == 2)
	{
		printf("%lld\n", (calc(a1, 3) + calc(a2, 3)) % mod);
		return;
	}

	Matrix a, b;

	a.matrix[1][1] = 1;
	a.matrix[1][2] = calc(x, 3);
	a.matrix[1][3] = 3 * calc(x, 2) % mod * y % mod;
	a.matrix[1][4] = 3 * x % mod * calc(y, 2) % mod;
	a.matrix[1][5] = calc(y, 3);

	a.matrix[2][1] = 0;
	a.matrix[2][2] = calc(x, 3);
	a.matrix[2][3] = 3 * calc(x, 2) % mod * y % mod;
	a.matrix[2][4] = 3 * x % mod * calc(y, 2) % mod;
	a.matrix[2][5] = calc(y, 3);

	a.matrix[3][1] = 0;
	a.matrix[3][2] = calc(x, 2);
	a.matrix[3][3] = 2 * x % mod * y % mod;
	a.matrix[3][4] = calc(y, 2);
	a.matrix[3][5] = 0;

	a.matrix[4][1] = 0;
	a.matrix[4][2] = x;
	a.matrix[4][3] = y;
	a.matrix[4][4] = 0;
	a.matrix[4][5] = 0;

	a.matrix[5][1] = 0;
	a.matrix[5][2] = 1;
	a.matrix[5][3] = 0;
	a.matrix[5][4] = 0;
	a.matrix[5][5] = 0;

	Matrix ans = qpow(a, n - 2);
	b.lenx = 5; b.leny = 1;
	b.matrix[1][1] = (calc(a1, 3) + calc(a2, 3)) % mod;
	b.matrix[2][1] = calc(a2, 3);
	b.matrix[3][1] = calc(a2, 2) * a1 % mod;
	b.matrix[4][1] = a2 * calc(a1, 2) % mod;
	b.matrix[5][1] = calc(a1, 3);

	ans = ans * b;
	printf("%lld\n", ans.matrix[1][1]);
}

int main()
{
#ifndef ONLINE_JUDGE
	freopen("input.in", "r", stdin);
	freopen("output.out", "w", stdout);
#endif
	int Case = read<int>();
	while(Case--) solve();
	return 0;
}

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