[bzoj 2875][noi 2012] 随机数生成器

题目大意

给定 (m)(a)(x0)(c)(n)(g),求递推式的第 (n) 项模 (g) 的余数: [
x
{n + 1} equiv a x_n + c ; (bmod m)
] (1 leqslant n, ; m, ; g ; leqslant 100,000,000)

(0 leqslant x_0, ; a, ; c ; leqslant 100,000,000)

(数据范围好像是这样。。。)

题目链接

BZOJ 2875

题解

矩阵乘法 + 快速幂。

代码

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

#include <cstring>
long long mod;
struct {
long long a[2][2];
Matrix(const bool unit) {
memset(a, 0, sizeof (a));
if (unit) for (int i = 0; i < 2; i++) a[i][i] = 1;
}
long long &operator()(const int i, const int j) {
return a[i][j];
}
const long long &operator()(const int i, const int j) const {
return a[i][j];
}
};
long long mul(long long a, long long b) {
long long res = 0;
for (; b; b >>= 1, a = (a + a) % mod) if (b & 1) res = (res + a) % mod;
return res;
}
Matrix operator*(const Matrix &a, const Matrix &b) {
Matrix res(false);
for (int i = 0; i < 2; i++)
for (int j = 0; j < 2; j++)
for (int k = 0; k < 2; k++)
(res(i, j) += mul(a(i, k), b(k, j))) %= mod;
return res;
}
Matrix pow(Matrix a, long long n) {
Matrix res(true);
for (; n; n >>= 1, a = a * a) if (n & 1) res = res * a;
return res;
}
int main() {
long long a, c, x, n, g;
scanf("%lld%lld%lld%lld%lld%lld", &mod, &a, &c, &x, &n, &g);
Matrix init(false);
init(0, 0) = x;
init(1, 0) = c;
Matrix shift(false);
shift(0, 0) = a;
shift(0, 1) = 1;
shift(1, 0) = 0;
shift(1, 1) = 1;
Matrix res = pow(shift, n) * init;
printf("%lldn", res(0, 0) % g);
}