数列$X_{n+1}=(aX_n+c)\mod m$
其中$a,c$是给定的常数,$n>0$。$X_0$的值已给出。
然后呢,你需要求出$X_n\mod g$。
$n,m,a,c,X_0\leq10^{18},g\leq 10^8$。
构造列向量
$$C_n=\begin{bmatrix}1\\X_n\end{bmatrix}$$
然后,构造转移矩阵
$$\begin{bmatrix}1&0\\c&a\end{bmatrix}C_n=C_{n+1}$$
嗯。然后要注意的:
$$a\mod m\mod g\not=a\mod \min(m,g)$$。
所以要用到神奇的long long乘法。
嗯。贴代码:
#include <bits/stdc++.h> using namespace std; typedef long long ll; typedef array<array<ll, 3>, 3> Matrix; ll P; Matrix A, I; inline ll MulMod(ll a, ll b, ll m){ ll t = a * b - (ll)((long double)a * b / m + 1e-10) * m; return (t %= m) < 0 ? t + m : t; } Matrix MatrixMul(const Matrix &A, const Matrix &B) { Matrix ret; for (int i=1; i<=2; i++) for (int j=1; j<=2; j++) { ret[i][j] = 0; for (int k=1; k<=2; k++) (ret[i][j] += MulMod(A[i][k], B[k][j], P)) %= P; } return ret; } Matrix PowerMod(ll k) { if (k == 0) return I; if (k == 1) return A; if (k & 1) return MatrixMul(PowerMod(k-1), A); Matrix B = PowerMod(k >> 1); return MatrixMul(B, B); } signed main() { I[1][1] = I[2][2] = 1; ll m,a,c,x0,n,g; scanf("%lld%lld%lld%lld%lld%lld", &m,&a,&c,&x0,&n,&g); P = m; A[1][1] = 1; A[1][2] = 0; A[2][1] = c; A[2][2] = a; Matrix ret = PowerMod(n); ll ans = (MulMod(x0, ret[2][2], m) + ret[2][1]) % m % g; if (ans < 0) { ans = (ans + (-ans / g) * g + g) % g; } printf("%lld\n", ans); return 0; }
原文:https://www.cnblogs.com/mchmch/p/9355875.html