这道题直接 的题解很多都是错的并且没有给出证明。
首先这道题等价于求 。
可以直接用高精度的矩阵快速幂,但是这里不讲。
不难发现在计算过程中矩阵一定是 的形式。
所以现在问题转化为了计算型为 的矩阵快速幂。
考虑讲矩阵对角化,也就是找到一个矩阵 满足 是一个对角矩阵,也就是说:
那么 。
证明:
接下来证明 。
只要证明 即可,显然:
现在来考虑什么时候能找到这么一个 ,先进行化简:
设 。
那么可以将上面等式变形为:
化简得:
所以当 时可以对角化,这种情况用矩阵对角化就可以解决。
当 时,发现就是每次加 ,那么很显然 ,然后分类讨论即可。
/*
* @Author: ftt2333
* @Email: ftt2333@126.com
* @LastEditTime: 2022-11-29 09:27:17
*/
#include <bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for (auto i = (a); i <= (b); ++i)
#define per(i, a, b) for (auto i = (a); i >= (b); --i)
#define all(v) (v).begin(), (v).end()
#define szof(v) int((v).size())
using pii = pair<int, int>;
using ll = long long;
#define gc() getchar()
#define pc(c) putchar(c)
template <class T = int> T read() {
T x = 0; char c = gc(); bool f = 0;
for (; !isdigit(c); c = gc()) f = c == '-';
for (; isdigit(c); c = gc()) x = x * 10 + c - 48;
return f ? -x : x;
}
template <class T> void write(T x) {
if (x >= 0) { if (x > 9) write(x / 10); pc(48 + x % 10); }
else { pc('-'); if (x < -9) write(-(x / 10)); pc(48 - x % 10); }
}
const int N = 1e6 + 10, mod = 1e9 + 7;
struct mat {
int a[2][2];
mat() { memset(a, 0, sizeof(a)); }
};
mat operator*(const mat &a, const mat &b) {
mat c;
rep(i, 0, 1) rep(j, 0, 1) rep(k, 0, 1)
(c.a[i][j] += 1ll * a.a[i][k] * b.a[k][j] % mod) %= mod;
return c;
}
mat qpow(mat a, int b) {
mat res;
res.a[0][0] = 1, res.a[0][1] = 0;
res.a[1][0] = 0, res.a[1][1] = 1;
for (; b; b >>= 1, a = a * a)
if (b & 1) res = res * a;
return res;
}
char nstr[N], mstr[N];
int nlen, mlen, a, b, c, d, n, m;
int main() {
scanf("%s%s", nstr + 1, mstr + 1);
a = read(), b = read(), c = read(), d = read();
int base0 = (a == 1 ? mod : mod - 1);
nlen = strlen(nstr + 1), mlen = strlen(mstr + 1);
rep(i, 1, mlen) {
m = (10ll * m + mstr[i] - 48 + base0) % base0;
}
mat A, B;
A.a[0][0] = a, A.a[0][1] = b;
A.a[1][0] = 0, A.a[1][1] = 1;
B.a[0][0] = c, B.a[0][1] = d;
B.a[1][0] = 0, B.a[1][1] = 1;
mat C;
C.a[0][0] = 1, C.a[0][1] = 0;
C.a[1][0] = 1, C.a[1][1] = 0;
mat D = qpow(A, (m + base0 - 1) % base0) * B;
int base1;
if (D.a[0][0] == 1) base1 = mod;
else base1 = mod - 1;
rep(i, 1, nlen) {
n = (10ll * n + nstr[i] - 48 + base1) % base1;
}
C = qpow(D, (n + base1 - 1) % base1) *
qpow(A, (m + base0 - 1) % base0) * C;
write(C.a[0][0]); pc(10);
}
in:
1145141919810 1000000007 2 1 1 2
ans:
283823589