题目大意
给定 m、a、x0、c、n、g,求递推式的第 n 项模 g 的余数:
xn+1≡axn+c(modm)
1⩽n,m,g⩽100,000,000
0⩽x0,a,c⩽100,000,000
(数据范围好像是这样。。。)
题目链接
【NOI 2012】随机数生成器 - LibreOJ 2670
题解
矩阵乘法 + 快速幂。
代码
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 <cstdio> #include <cstring> long long mod; struct Matrix { 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("%lld\n", res(0, 0) % g); }
|