题目来源:http://bestcoder.hdu.edu.cn/contests/contest_chineseproblem.php?cid=644&pid=1003
前面用奇偶性约掉2,后面处理前缀积和后缀积。
WA了很久的地方:在约掉2之前不能模(mod-1)
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
using namespace std;
typedef long long LL;
const int N = 100001;
LL Mod = 1000000007;
LL mod = Mod - 1;
char vis[N];
int prime[N];
vector<int> G[N];
int tot = 0;
void init_prime()
{
memset(vis, 0, sizeof(vis));
for(int i=2; i<N; i++)
{
if(!vis[i])
{
prime[++tot] = i;
for(int j=i; j<N; j+=i)
{
vis[j] = 1;
G[j].push_back(i);
}
}
}
}
LL quick(LL a, LL b)
{
LL c = 1;
while(b)
{
if(b&1)
c = c * a % Mod;
b >>= 1;
a = a * a % Mod;
}
return c;
}
int a[N];
LL num[N]; //素数i的个数
LL pre[N], suf[N];
int main()
{
init_prime();
int i, j, k, m, n;
while(scanf("%d", &n) == 1)
{
for(i=1; i<=n; i++)
scanf("%d", a+i);
memset(num, 0, sizeof(num));
for(i=1; i<=n; i++)
{
for(j=0; j<G[i].size(); j++)
{
int tp = 0, x = i;
while(x%G[i][j] == 0)
{
tp ++;
x /= G[i][j];
}
num[G[i][j]] += a[i] * tp;
}
}
///处理(p1+1)*(p2+1)*...*(px+1)的前缀积和后缀积
pre[0] = 1;
for(int i=1; i<=tot; i++)
{
pre[i] = pre[i-1];
if(num[prime[i]])
pre[i] = pre[i] * (num[prime[i]] % mod +1) % mod;
}
suf[tot+1] = 1;
for(int i=tot; i>=1; i--)
{
suf[i] = suf[i+1];
if(num[prime[i]])
suf[i] = suf[i] * (num[prime[i]] % mod +1) % mod;
}
/*---------------------------------------------*/
LL ans = 1;
for(int i=1; i<=tot; i++)
{
LL tmp, p = num[prime[i]];
if(p & 1)
tmp = p % mod * (((p+1)>>1) % mod) % mod;
else
tmp = (p>>1) %mod * ((p+1) % mod) % mod;
ans = ans * quick(prime[i], tmp * pre[i-1] % mod * suf[i+1] % mod) % Mod;
}
printf("%I64d
", ans);
}
return 0;
}