题目大意
给出一个数
n
n
n的质因数分解:
n
=
p
1
×
p
2
×
⋯
×
p
m
n = p_1 \times p_2 \times \cdots \times p_m
n=p1×p2×⋯×pm,
求
n
n
n的所有因数的乘积,模
1
0
9
+
7
10^9+7
109+7。
时间限制
2s
数据范围
m
≤
2
×
1
0
5
m \le 2\times 10^5
m≤2×105
p
i
≤
2
×
1
0
5
p_i\le 2\times 10^5
pi≤2×105,且保证
p
i
p_i
pi是质数
题解
n
n
n非常大,不可能计算出来,更加不可能枚举
n
n
n的因数,
换一种思路,就是考虑每个质因数对答案的贡献。
我们不妨将
n
n
n表示成
p
i
k
i
p_i^{k_i}
piki这种形式。
即
n
=
Π
i
=
1
m
p
i
k
i
n = \Pi_{i = 1} ^ m p_i ^ {k_i}
n=Πi=1mpiki
显然
n
n
n的因数个数就有
S
=
Π
i
=
1
m
k
i
+
1
S=\Pi_{i = 1}^m k_i+1
S=Πi=1mki+1
现在考虑一个质因数
p
i
p_i
pi对答案的贡献,
它自身可以组成的因数有:
p
i
0
,
p
i
1
,
⋯
,
p
i
k
i
p_i^0,p_i^1,\cdots,p_i^{k_i}
pi0,pi1,⋯,piki
它们出现的次数是
S
k
i
+
1
\frac{S}{k_i+1}
ki+1S
因此,总的贡献就是
(
Π
j
=
0
k
i
p
i
j
)
S
k
i
+
1
(\Pi_{j = 0}^{k_i} p_i^j)^{\frac{S}{k_i+1}}
(Πj=0kipij)ki+1S
根据欧拉公式,我们知道指数上的模数为
1
0
9
+
6
10^9+6
109+6,显然它不一定存在逆元,所以在这里需要特殊维护一下。
Code
//#pragma GCC optimize (2)
//#pragma G++ optimize (2)
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <iostream>
#include <vector>
#include <queue>
#define G getchar
#define ll long long
using namespace std;
int read()
{
char ch;
for(ch = G();(ch < '0' || ch > '9') && ch != '-';ch = G());
int n = 0 , w;
if (ch == '-')
{
w = -1;
ch = G();
} else w = 1;
for(;'0' <= ch && ch <= '9';ch = G())n = (n<<1)+(n<<3)+ch-48;
return n * w;
}
const int N = 200005;
const int mo = 1000000007;
int n , t;
int a[N] , nxt[N];
ll ans , s[N];
ll ksm(ll x , ll y)
{
ll s = 1;
for (; y ; )
{
if (y & 1) s = s * x % mo;
x = x * x % mo;
y = y >> 1;
}
return s;
}
int main()
{
//freopen("b.in","r",stdin);
//freopen("b.out","w",stdout);
n = read();
ans = 1;
for (int i = 0 ; i < n ; i++)
{
t = read();
a[t]++;
}
s[N - 1] = 1;
for (int i = 1 ; i < N ; i++)
if (a[i])
{
if (s[a[i] + 1] == 0)
{
int x = N - 1;
for (; nxt[x] ;)
{
s[x] = s[x] * (a[i] + 1) % (mo - 1);
x = nxt[x];
}
nxt[x] = a[i] + 1;
if (x != N - 1) s[a[i] + 1] = s[x] * x % (mo - 1); else s[a[i] + 1] = s[x];
s[x] = s[x] * (a[i] + 1) % (mo - 1);
}
else
{
int x = N - 1;
for (; x ;)
{
s[x] = s[x] * (a[i] + 1) % (mo - 1);
x = nxt[x];
}
}
}
for (int i = 1 ; i < N ; i++)
if (a[i]) ans = ans * ksm(i , (ll)a[i] * (a[i] + 1) / 2 % (mo - 1) * s[a[i] + 1] % (mo - 1)) % mo;
printf("%lld\n", ans);
return 0;
}