• 「题解」:x


    问题 A: x

    时间限制: 1 Sec  内存限制: 256 MB

    题面


    题面谢绝公开。

    题解


    赛时想到了正解并且对拍了很久。对拍没挂,但是评测姬表示我w0了……一脸懵逼。

    不难证明,如果对于两个数字$i,j$,$gcd_{i,j}>1$的话,那么这两个数字必定分在一组内,否则不满足条件。

    因此考虑对每一个数字质因数分解。包含同一质因数的数字不能分在同一集合。

    此时只需用并查集维护集合个数。最后统计集合分配即可。

    注意:每一个1都可以单独分配在一个集合里使得答案满足条件。因此每一个1都应单独放在一个集合中。特判即可。

    另外,直接质因数分解会T掉。事先筛一遍素数即可。(用了最慢的筛法,实测可过)

    #include<bits/stdc++.h>
    #define int long long
    #define rint register int
    #define read(A) A=init()
    #define mod 1000000007
    using namespace std;
    inline int init()
    {
        int a=0,b=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')b=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){a=(a<<3)+(a<<1)+ch-'0';ch=getchar();}
        return a*b;
    }
    int ToT,n,a[1000005],sum,prime[1000006],tot;
    int cnt,cp[1000003],pc[1000003],fa[1000003];
    bool vis[1000005],isnt[1000005];
    vector <int> v[1000003];
    inline int get_fa(int x){return (fa[x]==x)?x:fa[x]=get_fa(fa[x]);}
    inline int gcd(int A,int B){return (B==0)?A:gcd(B,A%B);}
    inline void I_get()
    {
        for(rint i=2;i<=1000000;++i)
        {
            if(!isnt[i])
            {
                prime[++tot]=i;int lin=2;
                while(lin*i<=1000000)isnt[lin*i]=1,lin++;
            }
        }
    }
    inline int qpow(int x,int y)
    {
        int num=1;
        while(y)
        {
            if(y&1)num=num*x%mod;
            x=x*x%mod;y>>=1;
        }
        return num;
    }
    inline void merge(int x,int y)
    {
        int fx=get_fa(x);
        int fy=get_fa(y);
        if(fx!=fy)sum--,fa[fy]=fx;
        return ;
    }
    inline void Devide(int id)
    {
        int x=a[id];
        for(rint i=1;prime[i]<=sqrt(x);++i)
        {
            if(x%prime[i]==0)
            {
                x/=prime[i];while(x%prime[i]==0)x/=prime[i];
                if(!vis[prime[i]])
                {
                    vis[prime[i]]=1;cp[++cnt]=prime[i];pc[prime[i]]=cnt;
                    v[cnt].clear();
                    v[cnt].push_back(id);
                }
                else v[pc[prime[i]]].push_back(id);
            }
        }
        if(x>1)
        {
            if(!vis[x])
            {
                vis[x]=1;cp[++cnt]=x;pc[x]=cnt;
                v[cnt].clear();
                v[cnt].push_back(id);
            }
            else v[pc[x]].push_back(id);
        }
        return ;
    }
    signed main()
    {
        read(ToT);I_get();
        while(ToT--)
        {
            read(n);sum=n;
            cnt=0;
            memset(vis,0,sizeof(vis));
            for(rint i=1;i<=n;++i)
            {
                read(a[i]);fa[i]=i;
                if(a[i]!=1)Devide(i);
            }
            for(rint i=1;i<=cnt;++i)
            {
                int lin=v[i][0];
                for(rint j=1;j<v[i].size();++j)
                    merge(lin,v[i][j]);
            }
            printf("%lld
    ",(qpow(2,sum)-2+mod)%mod);
            continue;
        }
    }
    View Code
  • 相关阅读:
    Oracle中TO_DATE格式
    实现带查询功能的Combox控件
    Combox和DropDownList控件的区别
    C# 获取字符串中的数字
    C# try catch finally 执行
    树形DP codevs 1814 最长链
    codevs 2822 爱在心中
    匈牙利算法 cojs.tk 搭配飞行员
    匈牙利算法 codevs 2776 寻找代表元
    2016-6-19 动态规划,贪心算法练习
  • 原文地址:https://www.cnblogs.com/xingmi-weiyouni/p/11606220.html
Copyright © 2020-2023  润新知