题目
简化题意
求 (large x_{i + 1} = (ax_i + c) mod m) 的第 (n) 项。
(large 1 leq n leq 10 ^ {18})。
思路
矩阵乘法。
递推用的矩阵也很好求。
(large left[egin{array}{ccc}x_i & cend{array} ight] imes left[egin{array}{ccc}a & 1 \ 1 & 1end{array} ight] = left[egin{array}{ccc}x_{i + 1} & cend{array} ight])
小心模数很大,乘起来会爆long long
所以要用龟速乘。
Code
#include <cstdio>
#include <cstring>
#include <string>
#include <iostream>
#include <algorithm>
typedef long long ll;
ll m, a, c, x0, n, g;
ll qmul(ll x, ll y) {
ll ans = 0;
while (y) {
if (y & 1) ans = ans + x, ans %= m;
x = (x + x) % m;
y >>= 1;
}
return ans % m;
}
struct Matrix {
ll jz[4][4];
Matrix() { memset(jz, 0, sizeof jz); }
void one() {
for (int i = 1; i <= 4; ++i) jz[i][i] = 1;
}
friend Matrix operator * (Matrix a, Matrix b) {
Matrix c;
for (int k = 1; k <= 2; ++k) {
for (int i = 1; i <= 2; ++i) {
for (int j = 1; j <= 2; ++j) {
c.jz[i][j] = (c.jz[i][j] + qmul(a.jz[i][k], b.jz[k][j])) % m;
}
}
}
return c;
}
};
Matrix qpow(Matrix a, ll b) {
Matrix ans, base = a;
ans.one();
while (b) {
if (b & 1) ans = ans * base;
base = base * base;
b >>= 1;
}
return ans;
}
int main() {
scanf("%lld %lld %lld %lld %lld %lld", &m ,&a, &c, &x0, &n, &g);
Matrix b, nor;
b.jz[1][1] = a % m, b.jz[1][2] = 0, b.jz[2][1] = 1, b.jz[2][2] = 1;
nor.jz[1][1] = x0 % m, nor.jz[1][2] = c % m;
b = qpow(b, n);
Matrix ans;
for (int k = 1; k <= 2; ++k) {
for (int i = 1; i <= 1; ++i) {
for (int j = 1; j <= 2; ++j) {
ans.jz[i][j] = (ans.jz[i][j] + qmul(nor.jz[i][k], b.jz[k][j])) % m;
}
}
}
std::cout << ans.jz[1][1] % g<< '
';
return 0;
}