zoukankan      html  css  js  c++  java
  • 建通道(位运算)

    链接:https://ac.nowcoder.com/acm/contest/3003/I
    来源:牛客网

    题目描述

    在无垠的宇宙中,有 n 个星球,第 i 个星球有权值 vi
    由于星球之间距离极远,因此想在有限的时间内在星际间旅行,就必须要在星球间建立传送通道。
    任意两个星球之间均可以建立传送通道,不过花费并不一样。第 i 个星球与第 j 个星球的之间建立传送通道的花费是 lowbit(vi⊕vj)
    其中 ⊕ 为二进制异或,而 lowbit(x) 为 x 二进制最低位 1 对应的值,例如 lowbit(5)=1,lowbit(8)=8。特殊地,lowbit(0)=0
    牛牛想在这 n 个星球间穿梭,于是――你需要告诉 牛牛,要使这 n 个星球相互可达,需要的花费最少是多少。

    输入描述:

    第一行,一个正整数 n 。
    第二行,n 个非负整数 v1,v2,,vn 。
    保证 1≤n≤2×1050≤vi<230

    输出描述:

    输出一行,一个整数表示答案。

    输入

    2
    1 2

    输出

    1

    说明

    12 号点之间建立通道,v1⊕v2=3,lowbit(3)=1。

    首先将权值去重(权值相等的点连接代价为 0 ),设去重后有 m 个点,接下来找到最小的二进制位 k ,满足存在 vi 的这个二进制位是 0 且存在 vj 的这个二进制位是  ,答案就是 2k×(m−1)

    (相当于所有这位是 0 的点与 j 点连边,是 1 的点与 i 点连边)。

    排序和去重以外时间复杂度 O(n+log⁡V),没有卡 O(nlog⁡V) ,好像两个 log 也过了。

    标程:

     1 #include <cstdio>
     2 #include <algorithm>
     3 using namespace std;
     4 const int N = 2e5 + 5;
     5 int n, k;
     6 int v[N], va, vo;
     7 long long ans;
     8 int main() {
     9   scanf("%d", &n);
    10   for (int i = 1; i <= n; i++)
    11     scanf("%d", &v[i]);
    12   sort(v + 1, v + n + 1);
    13   va = 0x7fffffff;
    14   for (int i = 1; i <= n; i++) {
    15     va &= v[i];
    16     vo |= v[i];
    17   }
    18   for (int i = n; i; i--)
    19     k += (v[i] != v[i + 1]);
    20   va ^= vo;
    21   for (int i = 0; i <= 30; i++) {
    22     int cur = 1 << i;
    23     if (va & cur) {
    24       ans = 1ll * cur * (k - 1);
    25       break;
    26     }
    27   }
    28   printf("%lld
    ", ans);
    29   return 0;
    30 }
    View Code
     1 #include <stdio.h>
     2 #include <string.h>
     3 #include <iostream>
     4 #include <string>
     5 #include <math.h>
     6 #include <algorithm>
     7 #include <vector>
     8 #include <stack>
     9 #include <queue>
    10 #include <set>
    11 #include <map>
    12 #include <sstream>
    13 const int INF=0x3f3f3f3f;
    14 typedef long long LL;
    15 const int mod=1e9+7;
    16 const int maxn=1e4+10;
    17 using namespace std;
    18 
    19 int a[200005];
    20 
    21 int main()
    22 {
    23     #ifdef DEBUG
    24     freopen("sample.txt","r",stdin);
    25     #endif
    26 
    27     int n;
    28     scanf("%d",&n);
    29     for(int i=1;i<=n;i++)
    30         scanf("%d",&a[i]);
    31     sort(a+1,a+1+n);
    32     n=unique(a+1,a+1+n)-(a+1);//去重
    33     if(n==1)
    34     {
    35         printf("0
    ");
    36         return 0;
    37     }
    38     for(int k=0;k<=n;k++)
    39     {
    40         int t0=0,t1=0; //在第i位上标记是否含有0 1
    41         for(int i=1;i<=n;i++)
    42         {
    43             if(a[i]&(1<<k)) t1++;
    44             else t0++;
    45         }
    46         if(t0&&t1)  //如果两种情况都有那么可以建立n-1条边
    47         {
    48             printf("%d
    ",(1LL<<k)*(n-1));
    49             return 0;
    50         }
    51     }
    52     
    53     return 0;
    54 }

    -

  • 相关阅读:
    jQuery火箭图标返回顶部代码
    jQuery火箭图标返回顶部代码
    jQuery火箭图标返回顶部代码
    jQuery火箭图标返回顶部代码
    jQuery火箭图标返回顶部代码
    关于http
    事件循环机制
    关于常问的输入URL到看到页面发生的全过程
    浅拷贝
    基础知识链接
  • 原文地址:https://www.cnblogs.com/jiamian/p/12275049.html
Copyright © 2011-2022 走看看