CF1325E Ehab‘s REAL Number Theory Problem
https://www.luogu.com.cn/problem/CF1325E
有些启发性的题目
首先发现 2 3 > 7 2^3 > 7 23>7 那么每个数最多为两个质数的乘积
如果有两个一样的数,或者本身就是完全平方数,直接输出即可
对于本身就是质数的,你补一个 1 1 1(虚点)
假设一个数可以表示为 x ∗ y x*y x∗y, x , y x,y x,y都是质数(或虚点1)
然后考虑每个质数为一个点,一个数就让 x − > y x->y x−>y
就转换成了求最小环
然后发现还是不太好做,枚举每个点跑bfs显然时间复杂度爆炸
发现 x , y x,y x,y一定至少有一个是 ≤ 1000 \le 1000 ≤1000的,所以环上必定有一个点是 ≤ 1000 \le 1000 ≤1000的,直接枚举1000以内的质数,然后大力bfs即可
#include<bits/stdc++.h>
#define N 2000050
using namespace std;
int ha[N], tot, ok[N], dis[N], ans, a[N], n, lst[N];
vector<int> g[N];
int id(int x) {
ok[x] = 1;
if(!ha[x]) ha[x] = ++ tot;
return ha[x];
}
void add(int X) {
int x = 1, y = X;
for(int i = 2; i * i <= y; i ++) if(y % i == 0) {
x = i; y /= i;
}
// printf("%d --> %d %d\n", x, y, X);
x = id(x), y = id(y);
g[x].push_back(y), g[y].push_back(x);
}
queue<int> q;
void solve(int s) {
if(!s) return ;
for(int i = 1; i <= tot; i ++) dis[i] = -1, lst[i] = 0;
dis[s] = 0; q.push(s);
while(q.size()) {
int u = q.front(); q.pop();
for(int v : g[u]) {
if(dis[v] == -1) {
dis[v] = dis[u] + 1;
lst[v] = u;
q.push(v);
} else if(v != lst[u]){
// printf("%d %d %d %d\n", dis[u], dis[v], u, v);
ans = min(ans, dis[u] + dis[v] + 1);
}
}
}
//for(int i = 1; i <= 10; i ++) printf("%d ", dis[i]); printf(" *%d\n", s);
}
int main() {
scanf("%d", &n);
for(int i = 1; i <= n; i ++) scanf("%d", &a[i]);
for(int i = 1; i <= n; i ++) {
for(int j = 2; j * j <= a[i]; j ++) while(a[i] % (j * j) == 0) a[i] /= (j * j);
}
//for(int i = 1; i <= n; i ++) printf(" %d ", a[i]); printf("\n");
sort(a + 1, a + 1 + n);
for(int i = 1; i <= n; i ++) {
int o = sqrt(a[i]);
if(o * o == a[i]) {
printf("1");
return 0;
}
}
for(int i = 2; i <= n; i ++) {
if(a[i] == a[i - 1]) {
printf("2");
return 0;
}
}
for(int i = 1; i <= n; i ++) add(a[i]);
ans = 1919810;
for(int i = 1; i <= 1000; i ++) if(ok[i]) solve(id(i));
if(ans > n) ans = -1;
printf("%d", ans);
return 0;
}