现在给出
求
先将式子变形
令中素数
的个数,一个数可以看成若干个素数为基底的次幂形式,比如
(2的个数为3)。那么
(这实际上是一个取对数的形式),既然一个数可以由若干个素数组成,那么
可以表示成
。
要得到可以用矩阵快速幂完成,然后乘以
的逆元就可以得到
。
这里用矩阵快速幂有一个注意点,因为最终结果表现为
,这里矩阵快速幂用来计算素数基底的个数,也就是次幂项,就是
,对于其中任一项
来说,结果要
,由欧拉定理
,其中
是素数;得
,等式两边同时可以乘以若干个
,即
,这时回到我们要求的
上来,我们在前面这个等式两边同时乘以
,即可以得到
,在题目中,我们通过快速幂可以得到的是
,将这个结果模
就能得到在
下
的大小。所以矩阵快速幂中要
,其余地方
。
另外在得到后,通过费马小定理求
的逆元时,我们
。
#include <bits/stdc++.h>
#define mem(a,b) memset(a, b, sizeof(a))
#define ll long long
#define pb push_back
#define fi first
#define se second
#define pi acos(-1)
#define eps 0.0001
using namespace std;
const int maxn = 1e6+ 5;
const int mod = 1e9+6;
const int mod1 = 1e9+7;
ll f1,f2,f3, c;
ll n;
//矩阵快速幂
struct matrix{
ll val[16][16];
matrix(){memset(val,0,sizeof(val));}
matrix operator*(const matrix & rhs)const{
matrix ret;
for(int i = 0; i < 16; i++)
for(int j = 0; j < 16; j++)
for(int k = 0; k < 16; k++)
ret.val[i][j] += val[i][k] * rhs.val[k][j]%mod,
ret.val[i][j] %= mod;
return ret;
}
};
matrix pow_mod(const matrix& b, ll p){
matrix ret, cur = b;
for(int i = 0; i < 16; i++)
ret.val[i][i] = 1;
while(p){
if(p & 1)
ret = ret * cur;
cur = cur * cur;
p>>=1;
}
return ret;
}
//快速幂
ll pow_mod1(ll a, ll p){
ll ans = 1;
while(p){
if(p & 1) ans = ans * a % mod1;
a = a * a % mod1;
p >>= 1;
}
return ans;
}
int main(){
cin >> n >> f1 >> f2 >> f3 >> c;
matrix p;
//快速幂矩阵
p.val[0][0] = p.val[1][0] = p.val[2][0] = 1;
p.val[0][1] = p.val[1][2] = 1;
p = pow_mod(p, n-3);
map<ll, ll> mp1,mp2,mp3;//分别计算f_x-1,f_x-2,f_x-3,对应特定的素数的次幂项
set<ll> Set;//收集所有素数基数
ll t3 = c;
for(ll i = 2; i <= sqrt(t3) && t3 > 1; i++){
if(t3 % i == 0){
Set.insert(i);
}
while(t3 % i == 0){
t3 /= i;
mp3[i]+=3;
mp2[i]+=2;
mp1[i]+=1;
}
}
if(t3 > 1) {
Set.insert(t3);
mp3[t3] += 3;
mp2[t3] += 2;
mp1[t3] += 1;
}
t3 = f3;
for(ll i = 2; i <= sqrt(t3) && t3 > 1; i++){
if(t3 % i == 0){
Set.insert(i);
}
while(t3 % i == 0){
t3 /= i;
mp3[i]++;
}
}
if(t3 > 1) {mp3[t3] += 1;Set.insert(t3);}
ll t2 = f2;
for(ll i = 2; i <= sqrt(t2) && t2 > 1; i++){
if(t2 % i == 0){
Set.insert(i);
}
while(t2 % i == 0){
t2 /= i;
mp2[i]++;
}
}
if(t2 > 1) {mp2[t2] += 1;Set.insert(t2);}
ll t1 = f1;
for(ll i = 2; i <= sqrt(t1) && t1 > 1; i++){
if(t1 % i == 0){
Set.insert(i);
}
while(t1 % i == 0){
t1 /= i;
mp1[i]++;
}
}
if(t1 > 1) {mp1[t1] += 1;Set.insert(t1);}
ll ans = 1LL;
for(auto w : Set){
matrix temp;
temp.val[0][0] = mp3[w];
temp.val[0][1] = mp2[w];
temp.val[0][2] = mp1[w];
temp = temp * p;
ans = ans * pow_mod1(w,temp.val[0][0]) % mod1;
}
ll suf = pow_mod1(c, n);
suf = pow_mod1(suf, mod1-2);
ans = suf * ans % mod1;
cout << ans << endl;
return 0;
}