题解 CF1182E 【Product Oriented Recurrence】
第一眼:很明显地递推啊
第二眼:
第三眼:很明显的矩阵加速啊
然后考场上成功地没写出来。
首先,我们在想到矩阵加速之后就可以发现,
然后,我们发现
于是我开始计算和化简:
显然,当我们要从
易得转移矩阵1为
问题在于怎么处理
还是可以写出
所以我们可以开一个
所以我们可以让
然后我们开始填这个矩阵:初始为
那么因为转移的时候,我们只需要让
然后,每转移一次需要让
完成了这些,会发现
下面我们要做的就是完成初始矩阵了。
显然,我们应该从
然后,计算答案矩阵为
最后,我们发现答案就是答案矩阵的
假设我们已经获得了
注意:我们对指数取模的时候,要模
总时间复杂度
附上代码:
#include <iostream>
#include <cmath>
#include <cstring>
#include <cstdio>
using namespace std;
const long long mod1 = 1e9 + 7ll, mod2 = 1e9 + 6ll;
struct Matrix {
long long a[10][10];
int n, m;
Matrix() {
n = m = 0;
memset(a, 0, sizeof(a));
}
//矩阵乘法
Matrix operator * (const Matrix& b) const {
Matrix c;
c.n = n;
c.m = b.m;
for (int i = 1;i <= c.n;i++) {
for (int j = 1;j <= c.m;j++) {
for (int k = 1;k <= m;k++) {
c.a[i][j] = (c.a[i][j] + (a[i][k] * b.a[k][j]) % mod2) % mod2;
}
}
}
return c;
}
};
long long n, f1, f2, f3, c;
//生成单位矩阵
Matrix Unit(int n) {
Matrix mtx;
mtx.n = n;
mtx.m = n;
for (int i = 1;i <= n;i++) {
for (int j = 1;j <= n;j++) {
mtx.a[i][j] = (i == j);
}
}
return mtx;
}
//矩阵快速幂
Matrix Power(Matrix x, long long y) {
Matrix ans = Unit(x.n);
while (y) {
if (y & 1) {
ans = ans * x;
}
y >>= 1;
x = x * x;
}
return ans;
}
//整数快速幂
long long Power_(long long x, long long y) {
long long ans = 1;
while (y) {
if (y & 1) {
ans = (ans * x) % mod1;
}
y >>= 1;
x = (x * x) % mod1;
}
return ans;
}
void Solve() {
//完成2个初始矩阵和2个转移矩阵
Matrix mtx1, mtx2, mtx3, mtx4;
mtx1.n = 1; mtx1.m = 3; mtx1.a[1][1] = mtx1.a[1][2] = mtx1.a[1][3] = 1;
mtx2.n = 3; mtx2.m = 3; mtx2.a[1][2] = mtx2.a[2][3] = mtx2.a[3][1] = mtx2.a[3][2] = mtx2.a[3][3] = 1;
mtx3.n = 1; mtx3.m = 5; mtx3.a[1][4] = 8; mtx3.a[1][5] = 1;
mtx4.n = 5; mtx4.m = 5; mtx4.a[1][1] = mtx4.a[1][2] = mtx4.a[2][1] = mtx4.a[2][3] = mtx4.a[3][1] = mtx4.a[4][1] = mtx4.a[4][4] = mtx4.a[5][5] = 1;
mtx4.a[5][1] = -6; mtx4.a[5][4] = 2;
//利用矩阵快速幂计算p,q,r,s
mtx1 = mtx1 * Power(mtx2, n - 4);
mtx3 = mtx3 * Power(mtx4, n - 3);
long long ans1 = mtx1.a[1][1], ans2 = mtx1.a[1][2], ans3 = mtx1.a[1][3], ans4 = mtx3.a[1][1];
long long ans = 1;
//求得最终答案
ans = (ans * Power_(f1, ans1)) % mod1;
ans = (ans * Power_(f2, ans2)) % mod1;
ans = (ans * Power_(f3, ans3)) % mod1;
ans = (ans * Power_(c, ans4)) % mod1;
printf("%I64d", ans);
}
int main() {
scanf("%I64d%I64d%I64d%I64d%I64d", &n, &f1, &f2, &f3, &c);
Solve();
return 0;
}