「题解」: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
原文地址:https://www.cnblogs.com/xingmi-weiyouni/p/11606220.html