題目大意:
給定n個正整數a1,a2,…,an,求下方式子的值(答案模10^9+7)。
題目解析:
首先,因爲歐拉函數是積性函數,對於每一個
方程變成
本來歐拉函數求篩法時某一個質數第一次出現乘
再次變換就可以得到:
於是我們只需要預處理出
/**************************************************************
Problem: 3560
User: szpszp
Language: C++
Result: Accepted
Time:4344 ms
Memory:15356 kb
****************************************************************/
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
#define MAXN 100000
#define MAXM
#define INF 0x3f3f3f3f
typedef long long int LL;
const LL MOD = 1000000007ll;
template<class T>
void Read(T &x){
x=0;char c=getchar();bool flag=0;
while(c<'0'||'9'<c){if(c=='-')flag=1;c=getchar();}
while('0'<=c&&c<='9'){x=x*10+c-'0';c=getchar();}
if(flag)x=-x;
}
struct node{
LL num,cnt;
bool operator < (const node &a)const{
if(num!=a.num)return num<a.num;
else return cnt<a.cnt;
}
};
int N;
node tmp[MAXN*9+10];
int len;
void Get_Divisor(int x){
for(int i=2;i*i<=x;++i)
if(x%i==0){
tmp[++len].num=i;
do{
++tmp[len].cnt;
x/=i;
}while(x%i==0);
}
if(x!=1)tmp[++len].num=x,tmp[len].cnt=1;
}
LL ksm(LL a,LL p){
LL rn=1;
while(p){
if(p&1)rn=(rn*a)%MOD;
a=(a*a)%MOD;
p>>=1;
}
return rn;
}
LL sum[30];
LL GetAns(int l,int r){
LL p=tmp[l].num;
LL rn=1;
sum[0]=1;
for(int i=1;i<=tmp[r].cnt;++i)
sum[i]=sum[i-1]*p%MOD;
for(int i=1;i<=tmp[r].cnt;++i)
sum[i]=(sum[i]+sum[i-1])%MOD;
for(int i=l;i<=r;++i)
rn=(rn*sum[tmp[i].cnt])%MOD;
--rn;
rn=(rn*ksm(p,MOD-2))%MOD;
rn=(rn*(p-1)+1)%MOD;
return rn;
}
int main(){
Read(N);
int x;
for(int i=1;i<=N;++i){
Read(x);
Get_Divisor(x);
}
sort(tmp+1,tmp+len+1);
LL ans=1;
int last=1;
for(int i=1;i<=len;++i){
if(i==len||tmp[i].num!=tmp[i+1].num){
ans=(ans*GetAns(last,i))%MOD;
last=i+1;
}
}
printf("%lld\n",(ans%MOD+MOD)%MOD);
}