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 xy 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;
}
posted @ 2021-12-04 08:08  lahlah  阅读(31)  评论(0编辑  收藏  举报