Loj 6440. 万能欧几里得

题目描述

https://loj.ac/p/6440

简要题意:求 $\sum_{i=0}^{n}A^iB^{\lfloor\frac{ai+b}{c}\rfloor}$,其中 $A$ 和 $B$ 均为 $N\times N$ 的矩阵

$a,b,c,n,\lfloor\frac{an+b}{c}\rfloor\le 10^{18},N\le 20$

Solution

我们考虑万能欧几里得算法,我们定义三元组 $(B^x,A^y,ans)$,容易得到 $(B^x,A^y,ans)\times (B^{x’},A^{y’},ans)=(B^{x+x’},A^{y+y’},A^yansB^x)$

时间复杂度 $O(N^3\log n)$

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
#include <iostream>
#define ll long long
using namespace std;

const int p = 998244353;

inline int add(int x, int y) { return (x += y) >= p ? x - p : x; }

int N;
struct Matrix {
int a[20][20];

Matrix() { clear(); }

void clear() { fill(a[0], a[0] + 400, 0); }
void setone() { for (int i = 0; i < N; ++i) a[i][i] = 1; }
friend Matrix operator * (const Matrix &u, const Matrix &v) {
Matrix w;
for (int k = 0; k < N; ++k)
for (int i = 0; i < N; ++i)
for (int j = 0; j < N; ++j)
w.a[i][j] = add(w.a[i][j], 1ll * u.a[i][k] * v.a[k][j] % p);
return w;
}
friend Matrix operator + (const Matrix &u, const Matrix &v) {
Matrix w;
for (int i = 0; i < N; ++i)
for (int j = 0; j < N; ++j) w.a[i][j] = add(u.a[i][j], v.a[i][j]);
return w;
}
friend Matrix pow(Matrix x, int n) {
Matrix s; s.setone();
for (; n; n >>= 1, x = x * x)
if (n & 1) s = s * x;
return s;
}
} I, A, B;

struct node {
Matrix x, y, ans;

node() { x.setone(); y.setone(); ans.clear(); }
node(const Matrix &x, const Matrix &y, const Matrix &ans) : x(x), y(y), ans(ans) {}

inline friend node operator * (const node &u, const node &v) {
return node(u.x * v.x, u.y * v.y, u.ans + u.y * v.ans * u.x);
}
friend node pow(node x, int n) {
node s;
for (; n; n >>= 1, x = x * x)
if (n & 1) s = s * x;
return s;
}
};
node calc(ll a, ll b, ll c, ll n, const node &A, const node &B) {
ll m = ((__int128) a * n + b) / c;
if (!m) return pow(B, n);
if (a >= c) return calc(a % c, b, c, n, A, pow(A, a / c) * B);
else return pow(B, (c - b - 1) / a) * A * calc(c, (c - b - 1) % a, a, m - 1, B, A) * pow(B, n - ((__int128) m * c - b - 1) / a);
}

ll n, a, b, c;

int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr); cout.tie(nullptr);

cin >> a >> c >> b >> n >> N; I.setone();
for (int i = 0; i < N; ++i)
for (int j = 0; j < N; ++j) cin >> A.a[i][j];
for (int i = 0; i < N; ++i)
for (int j = 0; j < N; ++j) cin >> B.a[i][j];
Matrix res = pow(B, b / c) * calc(a, b % c, c, n, node(B, I, Matrix()), node(I, A, A)).ans;
for (int i = 0; i < N; ++i)
for (int j = 0; j < N; ++j) cout << res.a[i][j] << " \n"[j == N - 1];
return 0;
}