[E. Ehab's REAL Number Theory Problem](https://codeforces.com/contest/1325/problem/E) 数论+图论 求最小环

E. Ehab's REAL Number Theory Problem 数论+图论 求最小环

题目大意:

给你一个n大小的数列,数列里的每一个元素满足以下要求:

  • 数据范围是:\(1<=a_i<=10^6\)
  • \(a_i\) 最多只有7个因数

题目要求在这个数列找到一个最短的子数列,子数列的所有的数相乘是一个完全平方数。

题解:

  • 这个题对于 \(x^{3}\) 应该等价于 \(x\) ,其实就是可以除去 \(a_i\)中的所有的平方项,显而易见,这个并不影响答案。
  • 因为 \(a_i\) 最多只有7个因素,由素数唯一分解定理可得每一个元素最多 2 个质因子。
  • 所以删去平方项之后,每一个元素就会要么是两个素因子相乘,要么就是一个素因子。
  • 此时,我们把每一个素因子当初一个节点,如果一个素数是由哪两个素因子相乘,那就可以连一条边,如果只有一个元素,把1也当作素因子看做一个节点。
  • 这样就变成一个图论问题,求无向无权图的最小环。
  • 直接暴力每一个点都是起点,因为每一个元素至少有一个素因子是小于1000,所以这个时候我们遍历从1到1000每一个值都是起点,就可以遍历到每一个元素,在这里求最小环即可。
#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
const int maxn=1e6+10;
struct node{
    int v,nxt;
    node(int v=0,int nxt=0):v(v),nxt(nxt){}
}e[maxn];
int head[maxn],cnt,isp[maxn],v[maxn],m,f,ans,a[maxn],num;
void init(){//只需要求1000以内的素数即可
    cnt=f=num=0,ans=inf;
    memset(head,-1,sizeof(head));
    for(int i=2;i<1000;i++){
        if(!v[i]){
            isp[m++]=i;
            v[i]=i;
        }
        for(int j=0;j<m;j++){
            if(v[i]<isp[j]||i*isp[j]>=1000) break;
            v[i*isp[j]]=isp[j];
        }
    }
}
void add(int u,int v){
    a[++num]=u,a[++num]=v;//求出所有的素数
    e[cnt]=node(v,head[u]);
    head[u]=cnt++;
    e[cnt]=node(u,head[v]);
    head[v]=cnt++;
}
void judge(int x){
    int div[5],tot=0;
    for(int i=0;i<m;i++){
        if(x%isp[i]==0){
            while(x%(isp[i]*isp[i])==0) x/=isp[i]*isp[i];
            if(x%isp[i]==0) div[++tot]=isp[i],x/=isp[i];
        }
    }
    if(tot==0&&x==1) {f=1;return ;}
    if(x>1) div[++tot]=x;
    if(tot==1) add(1,div[1]);
    else add(div[1],div[2]);
}
int d[maxn];
typedef pair<int,int>pii;
void bfs(int s){
    for(int i=1;i<=num;i++) d[a[i]]=inf;//只需要初始化在图中的素数
    d[s]=0;queue<pii>que;
    que.push(pii(s,0));
    while(!que.empty()){
        pii u=que.front();que.pop();
        for(int i=head[u.first];~i;i=e[i].nxt){
            int v=e[i].v;
            if(v==u.second) continue;
            if(d[v]==inf){
                d[v]=d[u.first]+1;
                que.push(pii(v,u.first));
            }
            else ans=min(ans,d[u.first]+d[v]+1);
        }
    }
}
int main(){
    init();int n;
    scanf("%d",&n);
    for(int i=1,x;i<=n;i++){
        scanf("%d",&x);judge(x);
    }
    sort(a+1,a+1+num);
    num=unique(a+1,a+1+num)-a-1;
    if(f) {printf("1\n");return 0;}
    bfs(1);
    for(int i=0;i<m;i++) bfs(isp[i]);
    if(ans==inf) printf("-1\n");
    else printf("%d\n",ans);
    return 0;
}


猜你喜欢

转载自www.cnblogs.com/EchoZQN/p/12558110.html