已知
给定 ,求 。
链接
题解
用矩阵乘法计算递推。
两个数相乘结果可能溢出,需要使用类似快速幂的方法拆成二进制每次乘 。
代码
#include <cstdio>
#include <cstring>
const long long MAXN = 1e18;
const long long MAXG = 1e8;
long long mod;
struct Matrix {
long long a[2][2];
Matrix(const bool unit = false) {
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() {
freopen("randoma.in", "r", stdin);
freopen("randoma.out", "w", stdout);
long long a, c, x, n, g;
scanf("%lld %lld %lld %lld %lld %lld", &mod, &a, &c, &x, &n, &g);
// mod = 1e9 + 7;
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;
#ifdef FORCE
Matrix res = init;
for (int j = 0; j < 2; j++) for (int k = 0; k < 2; k++) printf("%lld%c", res(j, k), k == 2 - 1 ? '\n' : ' ');
puts("----------------------");
for (int i = 0; i < n; i++) {
res = shift * res;
for (int j = 0; j < 2; j++) for (int k = 0; k < 2; k++) printf("%lld%c", res(j, k), k == 2 - 1 ? '\n' : ' ');
puts("----------------------");
}
#else
Matrix res = pow(shift, n) * init;
#endif
printf("%lld\n", res(0, 0) % g);
fclose(stdin);
fclose(stdout);
return 0;
}