E. Product Oriented Recurrence
Let fx=c2x−6⋅fx−1⋅fx−2⋅fx−3fx=c2x−6⋅fx−1⋅fx−2⋅fx−3 for x≥4x≥4.
You have given integers nn, f1f1, f2f2, f3f3, and cc. Find fnmod(109+7)fnmod(109+7).
Input
The only line contains five integers nn, f1, f2, f3, and c (4≤n≤10184≤n≤1018, 1≤f11≤f1, f2f2, f3f3, c≤109c≤109).
Output
Print fnmod(109+7)
Examples
input
5 1 2 5 3
output
72900
input
17 97 41 37 11
output
317451037
Note
In the first example, f4=90f4=90, f5=72900f5=72900.
In the second example, f17≈2.28×1029587f17≈2.28×1029587.
题意:求 fn.
思路:很容易发现对于 的指数有规律,设
为
所对应的指数。即当 n >= 7 时
对此,很容易想到矩阵快速幂。即构得初始矩阵a 为:
,其中 第 1 行 表示
的指数,第 2 行表示
的指数,第 3 行表示
的指数。第一二三列分别代表 n = 4, n = 5, n = 6 时的指数。
对此有 系数矩阵 A:
,因此 我们只需要对 A 做矩阵快速幂,然后再与原始矩阵相乘,即可得到
时的
的指数。
!!!值得注意的是,由于是对指数做的矩阵快速幂,所以我们需要利用 欧拉降幂 降幂公式,故取模的对象是 phi(1e9 + 7),即 1e9 + 6.
。。。。
剩下的就是 C 的指数,一开始只写了从 n = 4 开始的前面几项,发现指数是 2,6,14,30 还以为是 ,然后试了一发,连样例都过不了(
看来还是我太年轻了),看了题解 ,假设 C 的指数为CM,有:,由于矩阵快速幂需要 是递推式,化简有:
故可得矩阵为
, 推得 系数矩阵 A:
,然后利用相同的方式求得 C 的指数。
Code:
#include<bits/stdc++.h>
#define debug(x) cout << "[" << #x <<": " << (x) <<"]"<< endl
#define pii pair<int,int>
#define clr(a,b) memset((a),b,sizeof(a))
#define rep(i,a,b) for(int i = a;i < b;i ++)
#define pb push_back
#define MP make_pair
#define LL long long
#define ull unsigned LL
#define ls i << 1
#define rs (i << 1) + 1
#define INT(t) int t; scanf("%d",&t)
using namespace std;
const LL mod = 1e9 + 7;
const LL phip = 1e9 + 6;
const int maxn = 8;
struct mat{
LL m[maxn][maxn];
};
mat cal(mat A,mat B,int n){
mat C;
for(int i = 1;i <= n;i ++)
for(int j = 1;j <= n;j ++){
C.m[i][j] = 0;
for(int x = 1;x <= n;x ++){
C.m[i][j] = ((A.m[i][x] * B.m[x][j]) % phip + C.m[i][j]) % phip;
}
}
return C;
}
mat quick_mat(mat A,LL coun,int n){
mat C;
for(int i = 1;i <= n;i ++)
for(int j = 1;j <= n;j ++)
C.m[i][j] = (i == j);
while(coun > 0){
if(coun & 1) C = cal(C,A,n);
A = cal(A,A,n);
coun >>= 1;
}
return C;
}
LL quick_pow(LL a,LL b){
LL ans = 1;
while(b){
if(b & 1) (ans *= a) %= mod;
(a *= a) %= mod;
b >>= 1;
}
return ans;
}
LL cal_cimiC(LL x){
mat a; clr(a.m,0);
a.m[1][1] = 14; a.m[1][2] = 6;
a.m[1][3] = 2; a.m[1][4] = 4;
a.m[1][5] = 5; a.m[1][6] = -1;
if(x <= 6){
return x == 6 ? a.m[1][1] : (x == 5 ? a.m[1][2] : a.m[1][3]);
}
mat A; clr(A.m,0);
A.m[1][1] = A.m[2][1] = A.m[3][1] = A.m[4][1] = A.m[5][1] = A.m[6][1] = 1;
A.m[1][2] = A.m[2][3] = A.m[4][4] = A.m[5][5] = A.m[6][6] = 1;
A.m[6][4] = A.m[6][5] = -1;
A = quick_mat(A,x - 6,6);
a = cal(a,A,6);
return a.m[1][1];
}
int main() {
LL x,f1,f2,f3,c;
while(cin >> x >> f1 >> f2 >> f3 >> c){
mat a;
a.m[1][1] = 1; a.m[1][2] = 2; a.m[1][3] = 4;
a.m[2][1] = 1; a.m[2][2] = 2; a.m[2][3] = 3;
a.m[3][1] = 1; a.m[3][2] = 1; a.m[3][3] = 2;
LL cimi_c = cal_cimiC(x);
// debug(cimi_c);
LL F1,F2,F3;
if(x <= 6){
F1 = quick_pow(f1,a.m[3][x - 3]);
F2 = quick_pow(f2,a.m[2][x - 3]);
F3 = quick_pow(f3,a.m[1][x - 3]);
cout << quick_pow(c,cimi_c) * F1 % mod * F2 % mod * F3 % mod << endl;
continue;
}
mat A;
A.m[1][1] = 0; A.m[1][2] = 0; A.m[1][3] = 1;
A.m[2][1] = 1; A.m[2][2] = 0; A.m[2][3] = 1;
A.m[3][1] = 0; A.m[3][2] = 1; A.m[3][3] = 1;
A = quick_mat(A,x - 6,3);
a = cal(a,A,3);
F1 = quick_pow(f1,a.m[3][3]);
F2 = quick_pow(f2,a.m[2][3]);
F3 = quick_pow(f3,a.m[1][3]);
cout << quick_pow(c,cimi_c) * F1 % mod * F2 % mod * F3 % mod << endl;
}
return 0;
}