首先将1-n每个数分解质因数,变成p1^x1*p2^x2...pi^xi..pm^xm的形式,其中pi表示质因数,ai表示质因数出现次数。考虑每个质因数pi对最后答案的贡献,由约数个数定理知除pi以外的质因数有(x1+1)*(x2+1)*...(xi-1+1)*(xi+1+1)..(xm+1)个,而pi可能贡献0到xi个,所以包括pi的约数的积是pi^0*pi^1*...pi^xi*(x1+1)*(x2+1)*...(xi-1+1)*(xi+1+1)..(xm+1)=pi^[(xi+(xi+1))/2*(x1+1)*(x2+1)*...(xi-1+1)*(xi+1+1)..(xm+1)]。计算该指数的右部分可以使用前缀和和后缀和统计。由于这个指数相当大,可以使用费马小定理,对指数进行模(mod-1)。化简以后使用快速幂计算最后结果。
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<queue>
#include<cstring>
#include<iostream>
using namespace std;
typedef long long LL;
const int mod=1000000007;
const int mod2=1000000006;
const int maxn=500005;
const int N=500000;
int a[maxn];
vector<int> prime[maxn];
bool is[maxn];
void init()
{
memset(is,true,sizeof(is));
for(int i=2; i<=N; ++i)
{
if(!is[i]) continue;
prime[i].push_back(i);
for(int j=i+i; j<=N; j+=i)
{
prime[j].push_back(i);
is[j]=false;
}
}
}
LL cnt[maxn];
void calc(int x,int y)
{
int num=x;
for(int i=0; i<prime[x].size(); ++i)
{
int t=0;
while(num%prime[x][i]==0)
{
++t;
num/=prime[x][i];
}
cnt[prime[x][i]]+=t*y;
}
}
LL L[maxn],R[maxn];
LL sum(LL x)
{
LL y=x+1;
if(y%2==0) y/=2;
else x/=2;
x%=mod2;
y%=mod2;
return x*y%mod2;
}
LL quickPow(LL x,LL p)
{
LL res=1;
while(p>0)
{
if(p&1)
{
res*=x;
res%=mod;
}
x*=x;
x%=mod;
p>>=1;
}
return res;
}
int main()
{
init();
int n;
while(scanf("%d",&n)!=EOF)
{
memset(cnt,0,sizeof(cnt));
for(int i=1; i<=n; ++i)
{
scanf("%d",&a[i]);
calc(i,a[i]);
}
L[0]=R[n+1]=1;
for(int i=1; i<=n; ++i)
L[i]=L[i-1]*(cnt[i]+1)%mod2;
for(int i=n; i>=1; --i)
R[i]=R[i+1]*(cnt[i]+1)%mod2;
LL ans=1;
for(int i=2; i<=n; ++i)
{
if(!is[i]) continue;
LL p=sum(cnt[i])*(L[i-1]*R[i+1]%mod2)%mod2;
ans*=quickPow(i,p);
ans%=mod;
}
printf("%I64d\n",ans);
}
return 0;
}