首先学习一下抽屉原理:百度百科链接
总结一句话:把多于
(n不为0)个的物体放到n个抽屉里,则至少有一个抽屉里有不少于
的物体。
题意:给n个数,在
和
之间建一条权值为1的边当且仅当
&
!= 0,问最小环的长度
思路:
最多有
个,暴力存图都不可能开这么大的空间。就要优化,首先0肯定不用加进图中。
最大有
,也就是最大不超过
。
个数,每个数都有60个位置,只要这60个位置里至少有一个位置上有3个以上的1,那么答案就是3。所以我们需要某个位置上的 1的个数>=3,就把每个数都抽象成1,把
个数填到60个位置中,根据抽屉原理,
为121,所以不为0的数只要大于120就直接输出3即可
#include<bits/stdc++.h>
#define mid(l,r) (( l + r ) / 2)
#define lowbit(x) (( x & ( - x )))
#define lc(root) ((root * 2))
#define rc(root) ((root * 2 + 1))
#define me(array,x) (memset( array , x , sizeof( array ) ) )
typedef long long LL;
using namespace std;
const LL inf = 10000000;
const int mod = 1e9 + 7;
const int maxn = 1e6 + 10;
LL mp[500][500], dis[500][500], a[maxn];
LL n, cnt=0;
void init()
{
me(mp,0);
me(dis,0);
for(int i=1; i<=cnt; i++)
{
for(int j=1; j<=cnt ; j++)
{
if(a[i]&a[j])
mp[i][j] = dis[i][j] = 1;
else
mp[i][j] = dis[i][j] = inf;
}
}
}
int main()
{
scanf("%lld",&n);
for(int i = 1 ; i <= n ; i++)
{
LL x;
scanf("%lld",&x);
if(x != 0)
a[++cnt] = x;
}
if(cnt > 120)
printf("3\n");
else
{
init();
LL ans = inf;
for(int k=1; k<=cnt ; k++)
{
for(int i=1; i<k; i++)
{
for(int j=i+1; j<k; j++)
{
ans = min(ans,mp[i][j] + dis[i][k] + dis[k][j]);
}
}
for(int i = 1; i <= cnt ; i++)
{
for(int j =1 ; j <= cnt ; j++)
{
mp[i][j] = min(mp[i][j],mp[i][k]+mp[k][j]);
}
}
}
if(ans == inf)
printf("-1\n");
else
printf("%lld\n",ans );
}
return 0;
}