2019 牛客多校第五场 B - generator 1

题目链接:2019 牛客多校第五场 B

如果使用高精度每次除以2的操作是 \(O(10^6)\) 的,这里我们需要每次倍增规模让指数规模变小的操作是 \(O(1)\) 的,可以使用以10为单位倍增:

\[ A^b =\left\{  \begin{aligned}  &  [A^{\frac{b}{10}}] ^ {10} , & b \bmod 10 = 0 \\ &  [A^{\frac{b}{10}}] ^ {10} \times A^{b\bmod 10} ,  & b \bmod 10 \neq 0   \end{aligned} \right . \]

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
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int MAX_N = 1000000 + 5;
LL x[2], a, b, mod;
char n[MAX_N];
struct Matrix {
LL v[2][2];
Matrix(LL lu = 0, LL ru = 0, LL ld = 0, LL rd = 0) {
v[0][0] = lu; v[0][1] = ru; v[1][0] = ld; v[1][1] = rd;
}
inline friend Matrix operator * (const Matrix &l, const Matrix &r) {
Matrix ret;
ret.v[0][0] = ((l.v[0][0] * r.v[0][0]) % mod + (l.v[0][1] * r.v[1][0]) % mod) % mod;
ret.v[0][1] = ((l.v[0][0] * r.v[0][1]) % mod + (l.v[0][1] * r.v[1][1]) % mod) % mod;
ret.v[1][0] = ((l.v[1][0] * r.v[0][0]) % mod + (l.v[1][1] * r.v[1][0]) % mod) % mod;
ret.v[1][1] = ((l.v[1][0] * r.v[0][1]) % mod + (l.v[1][1] * r.v[1][1]) % mod) % mod;
return ret;
}
};
inline Matrix getPowStepTwo(Matrix o, LL y) {
Matrix ret = Matrix(1, 0, 0, 1);
while (y) {
if (y & 1) ret = ret * o;
o = o * o;
y >>= 1;
}
return ret;
}
Matrix getPowStepTen(Matrix o, char *s) {
int len = strlen(s);
Matrix tmp;
Matrix ret = Matrix(1, 0, 0, 1);
for (int i = len - 1; i >= 0; --i) {
int x = s[i] - '0';
if (x) ret = ret * getPowStepTwo(o, x);
// o = getPowStepTwo(o, 10);
tmp = o * o;
tmp = tmp * tmp;
tmp = tmp * tmp;
o = o * o * tmp;
}
return ret;
}
int main() {
scanf("%lld%lld%lld%lld", x, x + 1, &a, &b);
scanf("%s%lld", n, &mod);
Matrix ori = Matrix(a, b, 1, 0);
Matrix ans = getPowStepTen(ori, n);
LL out = ((ans.v[1][0] * x[1]) % mod + (ans.v[1][1] * x[0]) % mod) % mod;
printf("%lld\n", out);
return 0;
}