矩阵乘法 - CF678D Iterated Linear Function

CF678D Iterated Linear Function

题意

\(f_{i,x}=A\times f_{i-1,x} + B\)\(f_{0,x}=x\)\(f_{n,x}\)

思路

这道题的递推关系十分清晰。但由于数据范围大(\(1\le A,B,x\le 10^ 9,1\le n \le 10^{18}\)),所以这道题只能使用矩阵乘法加速递推。

矩阵的构造

我们需要构造一个矩阵 \(P\),使得 \(\begin{bmatrix} f_{0,x}& b\\ 0&0 \end{bmatrix}\times P= \begin{bmatrix} f_{1,x}&b\\ 0&0 \end{bmatrix}\)。根据矩阵乘法的规则,我们可以很容易地推出 \(P=\begin{bmatrix} A&0\\ 1&1\end{bmatrix}\)。由于 \(f_{0,x}=x\),所以要得到 \(f_{n,x}\) 就可以转化为求 \(\begin{bmatrix} x& b\\ 0&0 \end{bmatrix}\times P^n = \begin{bmatrix} f_{n,x}&b\\ 0&0 \end{bmatrix}\),使用矩阵快速幂解决。

code

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int mod = 1e9 + 7;
int m, n, x, y, a, b;
struct arr {
	int a[15][15];
	arr() {memset(a, 0, sizeof a);}
	arr operator*(const arr& B) const {//重载乘法
		arr cur;
		int r;
		for (int i = 1; i <= 2; ++i)
			for (int k = 1; k <= 2; ++k) {
				r = a[i][k];
				for (int j = 1; j <= 2; ++j)
					cur.a[i][j] += B.a[k][j] * r, cur.a[i][j] %= mod;
			}
		return cur;
	}
	arr operator^(int x) const {//重载快速幂
		arr cur, res;
		for (int i = 1; i <= 2; ++i) cur.a[i][i] = 1;
		for (int i = 1; i <= 2; ++i)
			for (int j = 1; j <= 2; ++j) res.a[i][j] = a[i][j] % mod;
		while (x) {
			if (x & 1) cur = cur * res;
			res = res * res;
			x >>= 1;
		}
		return cur;
	}
} A, F;//A对应上文中的P矩阵,F为答案矩阵
int mode(int x, int m) {return (x + m) % m;}
void init() {//初始化
	A.a[1][1] = a, A.a[1][2] = 0;
	A.a[2][1] = 1, A.a[2][2] = 1;
	F.a[1][1] = x, F.a[1][2] = b;
	F = F * (A ^ n);
}
signed main() {
	scanf("%lld%lld", &a, &b);
	scanf("%lld", &n);
	scanf("%lld", &x);
	init();
	printf("%lld", mode(F.a[1][1], mod));
	return 0;
}
posted @ 2024-01-14 10:47  固态H2O  阅读(3)  评论(0编辑  收藏  举报