• CF1325E. Ehab's REAL Number Theory Problem(最小环)


    题意:给出n个数$(n<=1e5)$,每个数不大于1e6,保证每个数因子数不多于7个,求一个最短的子串,使其积为某数的完全平方数。

    解题思路:做梦都没想到这是个图论的题。因子数不超过7个,说明每个数素因子最多两个,而若该数为素因子平方的倍数,可以将忽略,如27可以直接视为3,对结果不产生影响。因此,可以将每个数分解为两个素数之积,或一个素数。将每个数的两个素因子之间连一条边,若只有一个素因子则和1之间连一条边,最后找一个最小环即可。例如样例6,15,10,对于6会在2,3之间连边,15会在3,5之间连边,10会在2,5之间连边,这样的话会在2,3,5之间存在一个大小为3的环。

      而对于最终的答案,其所在环必然有一个点小于1000,因为$1000^{2}=1e6$,必不可能存在某数两个因子都大于1000,所以枚举1-1000中的素数和1为起点,找出最小环即可。而对于最小环,直接进行bfs搜索,当搜到某点时,若该点已经被访问过,则表示可以行成一个环,更新答案即可。时间复杂度$O(nsqrt{n}+1000n)$,给了3秒足够。

    贴上代码

    #include<bits/stdc++.h>
     
    using namespace std;
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    typedef pair <ll,ll> pii;
    #define rep(i,x,y) for(int i=x;i<y;i++)
    #define rept(i,x,y) for(int i=x;i<=y;i++)
    #define per(i,x,y) for(int i=x;i>=y;i--)
    #define all(x) x.begin(),x.end()
    #define pb push_back
    #define fi first
    #define se second
    #define mes(a,b) memset(a,b,sizeof a)
    #define mp make_pair
    #define dd(x) cout<<#x<<"="<<x<<" "
    #define de(x) cout<<#x<<"="<<x<<"
    "
    #define debug() cout<<"I love Miyamizu Mitsuha forever.
    "
    const int inf=0x3f3f3f3f;
    const int maxn=1e5+5;
    const int maxm=1e6+5;
    int head[maxm],to[maxm<<1],nex[maxm<<1],tot=0;
    int a[maxn];
    int prime[100000],cnt=0;
    bool vis[maxm];
     
    void add(int a,int b)
    {
        to[tot]=b;nex[tot]=head[a];head[a]=tot++;
        to[tot]=a;nex[tot]=head[b];head[b]=tot++;
    }
    queue<pii> q;
    int dis[maxm];
    int bfs(int st)
    {
        mes(dis,-1);
        while(!q.empty()) q.pop();
        q.push(mp(st,-1));
        dis[st]=0;
        int ans=inf;
        while(!q.empty())
        {
            int point=q.front().fi,e=q.front().se^1;
            q.pop();
            for(int j=head[point];j!=-1;j=nex[j])
            {
                if(j==e) continue;
                if(dis[to[j]]!=-1)
                {
                    ans=min(ans,dis[to[j]]+dis[point]+1);
                    continue;
                }
                dis[to[j]]=dis[point]+1;
                q.push(mp(to[j],j));
            }
        }
        return ans;
    }
    void solve(int n)
    {
        mes(vis,0);
        vis[1]=1;
        rept(i,2,n)
        {
            if(!vis[i])
            {
                prime[cnt++]=i;
            }
            rep(j,0,cnt)
            {
                if(i*(ll)prime[j]>n) break;
                vis[i*prime[j]]=1;
                if(i%prime[j]==0) break;
            }
        }
    }
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        mes(head,-1);
        int n;
        cin>>n;
        solve(1000000);
        rep(i,0,n) cin>>a[i];
        rep(i,0,n)
        {
            rep(j,0,cnt)
            {
                if(a[i]%prime[j]==0)
                {
                    ll s=(ll)prime[j]*prime[j];
                    while(a[i]%s==0) a[i]/=s;
                    if(a[i]%prime[j]==0)
                    {
                        s=sqrt(a[i]/prime[j]);
                        if(s*s==a[i]/prime[j]) add(1,prime[j]);
                        else add(prime[j],a[i]/prime[j]);
                    }
                    else add(1,a[i]);
                    break;
                }
                if(a[i]/prime[j]<prime[j])
                {
                    add(1,a[i]);
                    break;
                }
            }
        }
        int ans=inf;
        rep(i,1,1000)
            if(!vis[i]||i==1) ans=min(ans,bfs(i));
        if(ans==inf) cout<<"-1
    ";
        else cout<<ans<<"
    ";
        return 0;
    }
  • 相关阅读:
    站立会议第1天
    博客园用户体验
    风险评估
    寻找正整数中1的个数
    每个小组对本组的意见
    对每个小组的评论和建议
    每日scrum(六)
    每日scrum(五)
    分析电脑控制的丹佛机场行李系统
    每日scrum(四)
  • 原文地址:https://www.cnblogs.com/FZUzyz/p/12577014.html
Copyright © 2020-2023  润新知