题解 洛谷P7384【「EZEC-6」】

概述

题号 难度 \(AC\)时间及记录
\(\texttt{P7384}\) \(\texttt{洛谷难度:暂无评定}\) \(\texttt{On 2021/02/21}\)

解析

这道题我们考虑并查集暴力
不难证明,众所周知,每两个数,他们在二进制下,
如果某一位同是\(1\),那么他们应该归为一组,
这样代价最小。
因此,学过状态压缩\(DP\)的同学应该已经知道怎么做了。
如果某个数是\(0\),记得特判。
某一位没用过特殊处理,
即可\(AC\)
时间复杂度\(\mathcal{O(nlogn)}\)

代码

/*
Author:Xsmyy
Problem:P7384
Date:2021/02/21
*/
#include<bits/stdc++.h>
#define BetterIO ios::sync_with_stdio(false)
using namespace std;
int N;
int Fa[101];
bool Used[101];
int A[101][101];
#define getchar()(X==Y&&(Y=(X=sRead)+fread(sRead,1,1<<21,stdin),X==Y)?EOF:*X++)
char sRead[1<<21],*X=sRead,*Y=sRead;
inline long long Read()
{
    register long long Return,Flag;
    Return=Flag=0;
    register char C;
    C=getchar();
    for(;!isdigit(C);C=getchar())
    {
        Flag^=!(C^45);
    }
    for(;isdigit(C);C=getchar())
    {
        Return=(Return<<1ll)+(Return<<3ll)+(C^'0');
    }
    if(Flag)
    {
        Return=-Return;
    }
    return Return;
}
inline int Find(int X)
{
    return X==Fa[X]?X:Fa[X]=Find(Fa[X]);
}
inline void Merge(int X,int Y)
{
    Fa[Find(X)]=Find(Y);
}
int main(void)
{
	BetterIO;
	register int i,j;
	N=Read();
	for(i=0;i<=64;i++)
	{
		Fa[i]=i;
	}
	register int Ans;
	Ans=0;
	for(i=1;i<=N;i++)
	{
		register long long X;
		X=Read();
		if(!X)
		{
			Ans++;
			continue;
		}
		register int One;
		One=-1;
		register long long i;
		for(i=0;(1ll<<i)<=X;i++)
		{
			if((1ll<<i)&X)
			{
				if(One!=-1)
				{
					A[i][One]=true;
				}
				else
				{
					One=i;
				}
				Used[i]=true;
			}
		}
	}
	for(i=0;i<=64;i++)
	{
		for(j=0;j<=64;j++)
		{
			if(A[i][j])
			{
				Merge(i,j);
			}
		}
	}
	for(i=0;i<=64;i++)
	{
		if(Fa[i]==i&&Used[i])
		{
			Ans++;
		}
	}
	cout<<Ans<<endl;
	return 0;
}
posted @ 2021-02-21 09:34  Bushuai_Tang  阅读(38)  评论(0编辑  收藏  举报