前言:半夜写的题解,如果有什么没写清楚就是神智不清了(
题目链接 : 4954:矩阵游戏 (tzcoder.cn)
前置知识点:欧拉降幂,矩阵乘法,矩阵快速幂
欧拉降幂 :
(具体推论请移步欧拉降幂的证明)
其中 代表欧拉函数值
特判a=1 的情况,
此时 P 的行列式为 0,不存在 P的逆矩阵,因此不可以对角化。
因此当且仅当 a≠1 时可以对角化。
解题思路与过程:
code:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
//const int INF = 0x3f3f3f3f;
typedef pair<ll, ll> PII;
const int maxn = 2005;
const int N = 1e6 + 50;
const ll mod = 1e9+7;
const int P = 131;
const ll pz = 131, py = 13331;
ll n, m, k, s;
ll a, b, c, d;
struct Max {
ll r, c;
ll a[3][3];
Max() { memset(a, 0, sizeof(a)); }
void init(int c1, int r1, int d, int x1, int x2, int y1, int y2) {
r = r1, c = c1;
if (c1 == 1)
for (int i = 1; i <= c1; i++)
for (int j = 1; j <= r1; j++)
a[i][j] = d;
else
{
// cout << c1 << " " << r1 << endl;
a[1][1] = x1; a[1][2] = x2;
a[2][1] = y1; a[2][2] = y2;
}
}
Max operator*(const Max& b)const
{
Max res;
for (int i = 1; i <= 2; i++)
for (int j = 1; j <= 2; j++)
for (int k = 1; k <= 2; k++)
res.a[i][j] = (res.a[i][j] + a[i][k] * b.a[k][j]) % mod;
return res;
}
};
void pr(Max ret)//检测输出
{
cout << ret.a[1][1] << " " << ret.a[1][2] << "\n" << ret.a[2][1] << " " << ret.a[2][2] << endl;
}
Max ksm(Max tmp, ll p)//矩阵快速幂
{
Max ret;
ret.init(2, 2, 0, 0, 0, 0, 0);
for (int i = 1; i <= 2; i++)
ret.a[i][i] = 1;
while (p)
{
if (p & 1) ret = ret * tmp;
// pr(ret);
tmp = tmp * tmp;
p >>= 1;
}
return ret;
}
inline void solve()
{
string sn, sm;
cin >> sn >> sm >> a >> b >> c >> d;
ll l1 = sn.size(), l2 = sm.size();
for (int i = 0; i < l1; i++)
{
n = n * 10 + (sn[i] - '0');
if (a == 1)n %= mod;
// 特判1是因为若a=1矩阵会出现矩阵没有逆矩阵的情况,此时不能对角赋值为1
else n %= mod - 1; //欧拉降幂
}
for (int i = 0; i < l2; i++)
{
m = m * 10 + (sm[i] - '0');
if (a == 1)m %= mod;
// 特判1是因为若a=1矩阵会出现矩阵没有逆矩阵的情况,此时不能对角赋值为1
else m %= mod - 1; //欧拉降幂
}
Max x,f, g1, g2,ans;
f.init(1, 2, 1, 0, 0, 0, 0);
g1.init(2, 2, 0, a, 0, b, 1);
g2.init(2, 2, 0, c, 0, d, 1);
x = ksm(g1, m - 1) * g2;
x = ksm(x, n - 1);
ans = f * x;
//pr(ans);
Max y = ksm(g1, m - 1);
ans = ans * y;
cout << ans.a[1][1];
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
int t = 1;
//cin >> t;
while (t--)
solve();
return 0;
}