[CF1182E] Product Oriented Recurrence - 矩阵快速幂
Description
当 (x geq 4) 时,(f_x = c^{2x - 6} cdot f_{x - 1} cdot f_{x - 2} cdot f_{x - 3}) 。现在已知 (n,f_1,f_2,f_3,c) 的值,求 (f_n) 的值,对 (10^9 + 7) 取模。((4 leq n leq 10^{18},1 leq f_1,f_2,f_3,c leq 10^9))
Solution
显然 (f_n=c^?f_1^?f_2^?f_3^?),指数显然是可以线性递推的,用矩阵快速幂优化即可
#include <bits/stdc++.h>
using namespace std;
#define int long long
int n, f1, f2, f3, c;
const int MOD = 1e9 + 7;
const int mod = 1e9 + 6;
struct Matrix
{
int n, m;
int a[7][7];
Matrix()
{
memset(a, 0, sizeof a);
}
int *operator[](int id)
{
return a[id];
}
Matrix operator*(const Matrix &rhs)
{
assert(m == rhs.n);
Matrix res;
res.n = n;
res.m = rhs.m;
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= rhs.m; j++)
{
for (int k = 1; k <= m; k++)
{
res[i][j] += a[i][k] * rhs.a[k][j];
res[i][j] %= mod;
}
}
}
return res;
}
};
Matrix a0, a1, b0, b1, b2, b3;
Matrix qpow(Matrix p, int q)
{
Matrix I;
I.n = p.n;
I.m = p.m;
for (int i = 1; i <= I.n; i++)
I[i][i] = 1;
return (q & 1 ? p : I) * (q ? qpow(p * p, q / 2) : I);
}
const int eff[] = {1, 1, 1, 2, mod - 4, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 3, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0};
void load()
{
int pos = 0;
a0.n = a0.m = 5;
for (int i = 1; i <= 5; i++)
for (int j = 1; j <= 5; j++)
a0[i][j] = eff[pos++];
a1.n = a1.m = 3;
for (int i = 1; i <= 3; i++)
for (int j = 1; j <= 3; j++)
a1[i][j] = eff[pos++];
b0.n = 5;
b0.m = 1;
b1.n = 3;
b1.m = 1;
b2.n = 3;
b2.m = 1;
b3.n = 3;
b3.m = 1;
for (int i = 1; i <= 5; i++)
b0[i][1] = eff[pos++];
for (int i = 1; i <= 3; i++)
b1[i][1] = eff[pos++];
for (int i = 1; i <= 3; i++)
b2[i][1] = eff[pos++];
for (int i = 1; i <= 3; i++)
b3[i][1] = eff[pos++];
}
int calc(int n, Matrix a, Matrix b)
{
n -= 3;
Matrix c = qpow(a, n);
Matrix d = c * b;
return d[1][1];
}
int qpow(int p, int q)
{
return (q & 1 ? p : 1) * (q ? qpow(p * p % MOD, q / 2) : 1) % MOD;
}
int getf()
{
int qc = calc(n, a0, b0);
int q1 = calc(n, a1, b1);
int q2 = calc(n, a1, b2);
int q3 = calc(n, a1, b3);
return qpow(c, qc) * qpow(f1, q1) % MOD * qpow(f2, q2) % MOD * qpow(f3, q3) % MOD;
}
signed main()
{
ios::sync_with_stdio(false);
load();
cin >> n >> f1 >> f2 >> f3 >> c;
cout << getf() << endl;
}