题面找其中的L题:https://upload-file.xcpcio.com/icpc/2020/2020-ICPC-Asia-East-Continent-Final-Statement.pdf
这次学到了快速求质因数分解,即欧拉筛过程保存每个数的最小质数,在分解的时候每次除以自己的最小质数即可。
该题是一个明显的思维题,想了好久没做出来然后找题解,发现压根找不到详细的题解(参加EC-Final的大神们并不屑于对该签到水题有过多叙述😢)。只有看到什么全是0,全是1的一些提示。
最后终于想到了,只看一个质数 p p p的话,对每个位置的 a i a_i ai都算一下该质数作为其因数的指数是多少,根据题面意思,必须通过修改 t i t_i ti,让所有位置的 a i t i {a_i}{t_i} aiti 的对应指数都是奇数或者偶数,因此有两种选择,选变动次数最少的那种即可。
#include <bits/stdc++.h>
using namespace std;
using LL = long long;
const LL MOD = 1000000007;
const int N = 1000000 + 5;
LL ksm(LL a, LL b) {
LL res = 1;
while (b) {
if (b & 1) res = res * a % MOD;
a = a * a % MOD;
b >>= 1;
}
return res;
}
LL inv(LL x) {
return ksm(x, MOD - 2);
}
int n, cnt, f[N], p[N], s[N];
int vis[N], hav[N], num[N];
void init() {
s[1] = 1;
for (int i = 2; i < N; i++) {
if (!f[i]) p[++cnt] = i, s[i] = i;
for (int j = 1; j <= cnt; j++) {
if (i * p[j] >= N) break;
f[i * p[j]] = 1;
s[i * p[j]] = p[j];
if (i % p[j] == 0)break;
}
}
}
int main(void) {
// freopen("in.txt", "r", stdin);
init();
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
LL x;
scanf("%lld", &x);
int tot = 0;
while (x != 1) {
if (!vis[s[x]])
hav[++tot] = s[x];
vis[s[x]]++;
x /= s[x];
}
for (int j = 1; j <= tot; j++) {
if (vis[hav[j]] & 1) num[hav[j]]++;
vis[hav[j]] = 0;
}
}
LL ans = 1;
for (int i = 1; i <= cnt; i++) {
if(!num[p[i]]) continue;
ans = ans * ksm(p[i], min(num[p[i]], n - num[p[i]])) % MOD;
}
printf("%lld\n", ans);
return 0;
}