• 【SSLOJ1480】X


    题目

    思路

    显然任意两个 \(\gcd\) 不为 \(1\) 的数字必须分到一个组里。所以可以在筛质数的同时将有相同质因数的数字归到一个集合内,设最终有 \(m\) 个集合,那么答案为 \(2^m-2\)(减去两个空集合情况)。
    我采用埃氏筛 + 并查集,时间复杂度 \(O(n\log \log n)\)。事实上暴力枚举质因数 + dfs 也是可以的。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    const int N=100010,M=1000010,MOD=1e9+7;
    int Q,n,m,father[M];
    bool vis[M],v[M];
    
    void prework()
    {
    	for (int i=0;i<M;i++)
    		father[i]=i,vis[i]=v[i]=0;
    	m=0;
    }
    
    int find(int x)
    {
    	return x==father[x]?x:father[x]=find(father[x]);
    }
    
    ll fpow(ll x,int k)
    {
    	ll ans=1;
    	for (;k;k>>=1,x=x*x%MOD)
    		if (k&1) ans=ans*x%MOD;
    	return ans;
    }
    
    int main()
    {
    //	freopen("data.txt","r",stdin);
    	scanf("%d",&Q);
    	while (Q--)
    	{
    		prework();
    		scanf("%d",&n);
    		for (int i=1,x;i<=n;i++)
    		{
    			scanf("%d",&x);
    			vis[x]=1;
    			if (x==1) m++;
    		}
    		for (int i=2,last;i<M;i++)
    		{
    			if (v[i]) continue;
    			if (vis[i]) last=i;
    				else last=0;
    			for (int j=i*2;j<M;j+=i)
    			{
    				v[j]=1;
    				if (vis[j])
    				{
    					if (last) father[find(j)]=find(last);
    					last=j;
    				}
    			}
    		}
    		for (int i=2;i<M;i++)
    			if (vis[i] && find(i)==i) m++;
    		printf("%lld\n",(fpow(2LL,m)-2LL+MOD)%MOD);
    	}
    	return 0;
    }
    
  • 相关阅读:
    内置函数详解
    lambda函数
    第八章(5)
    第八章(4)
    第八章(3)
    第八章(2)
    第八章(1)
    第七章(3)
    第七章(2)
    第七章(1)
  • 原文地址:https://www.cnblogs.com/stoorz/p/13498045.html
Copyright © 2020-2023  润新知