CF615D题解

题意

以给定质因子的形式给定一个数 $n$,并给出具体的质因子,求:

$$\prod_{d\mid n}d$$

Solution

我们唯一分解 $n$,使得 $n=\prod p_i^{\alpha_i}$,我们考虑对于每一个素数 $p_i$,它在质因子中可能以 $p_i^k(0\le k\le \alpha_i)$ 的形式出现,即一共 $\frac{\alpha_i\times(\alpha_i+1)}{2}$ 次。并且对于每个幂 $k$,都会在别的质因子取任何值的时候出现,即对于一个 $p_i^k$,它会出现 $\frac{\prod_j(\alpha_j+1)}{\alpha_i+1}$ 次,因此它的贡献就是

$$p_i^{\frac{\prod_j(\alpha_j+1)}{\alpha_i+1}\times\frac{\alpha_i\times(\alpha_i+1)}{2}}=p_i^{\frac{\alpha_i\prod(\alpha_i+1)}{2}}$$

这个东西就计算 $\prod(\alpha_i+1)$,然后每次乘 $\alpha_i$ 放在 $p_i$ 的指数上。

记 $s=\prod(\alpha_i+1)$,于是现在的答案就是

$$\prod p_i^{\frac{s\times \alpha_i}{2}}$$

但是 $s\times \alpha_i$ 可能会非常大,而且它在指数上,因此我们用拓展欧拉公式对指数进行降幂。

因为 $\alpha_i$ 与 $\alpha_i+1$ 都在乘积中,因此除以二一定为整数。但对于模数的情况下,我们并不能保证是整数,因此我们还需要进行判断。

  • 对于 $\alpha_i+1$ 有偶数的情况,再求乘积的时候就将某个 $\alpha_i+1$ 除以二,后面直接乘 $\alpha_i$ 就行。

  • 对于 $\alpha_i+1$ 全部为奇数,即 $\alpha_i$ 全部为偶数,直接在最后计算的时候将 $\alpha_i$ 除以二再乘进去就可以了。

具体的看代码吧。

CODE

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#include<iostream>
#include<cstdio>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<string>
#include<cstring>
#include<queue>
#include<stack>
#include<set>
#include<vector>
#include<map>

using namespace std;

const int N = 2e5 + 10;
const int M = 2e5 + 10;
#define endl '\n'
#define int long long
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;

int n,m,phi=MOD-1;
int t[N],cnt,sum=1;
bool flag=false;

int ksm(int x,int k){
int ans=1;
while(k){
if(k&1) ans=ans*x%MOD;
x=x*x%MOD; k>>=1;
}
return ans;
}

signed main(){
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
cin>>n;
for(int i=1,x;i<=n;++i) cin>>x, t[x]++, m=max(m,x);
for(int i=1;i<=m;++i){
if((t[i]+1)%2==0&&!flag) sum=sum*(t[i]+1)/2%phi, flag=true;
else sum=sum*(t[i]+1)%phi;
}
int ans=1;
for(int i=1;i<=m;++i){
if(t[i]==0) continue;
int y;
if(flag) y=sum*t[i]%phi;
else y=sum*t[i]/2%phi;
ans=ans*ksm(i,y+phi)%MOD;
}
cout<<ans<<endl;
return 0;
}