zoukankan      html  css  js  c++  java
  • Atcoder Grand Contest 20 C(bitset优化背包)

    传送门:

    题意:

    给你nn个数,现在一共可以形成2n12^{n}-1个集合。他们的和能够形成一个新的数列。现在问你这个新的数列的中位数是多少。

    题目分析:

    首先需要知道,一个数列的中位数必定是大于等于(i=1nai)/2(sum_{i=1}^{n}a_i)/2,证明如下。

    设集合AA能够分为P,QP,Q两个不同的子集,且(PQ=AP igcup Q=A)。此时对于集合P,QP,Q中的所有数,一定有P+Q=Asum P+sum Q=sum A。我们假设PQsum P le sum Q,则有P12Asum P le frac{1}{2}*sum A,同时有Q12Asum Q ge frac{1}{2}*sum A

    而又因为集合PQ=AP igcup Q=A,故我们可以假设PP属于AA的前半部分,即:P1=A1,P2=A2P2n11=A2n11P_1=A_1,P_2=A_2 dots P_{2^{n-1}-1}=A_{2^{n-1}-1}。同时Q属于AA的后半部分,即:P2n1=A2n1P2n1=A2n1P_{2^{n-1}}=A_{2^{n-1}} dots P_{2^{n}-1}=A_{2^{n}-1}

    因此我们只需要找到第一个大于等于12Afrac{1}{2}sum{A}的数即可。

    而这个此时我们的问题即转化为,让你从这个数列中选取一个子序列,使得子序列的和为12Afrac{1}{2}sum{A}。而这个问题我们可以用可达性01背包去解决。

    但是如果直接去做,时间复杂度为O(n2max(ai))mathcal{O}(n^2max(a_i)),显然不符合条件。

    而考虑到这是一个可达性只有0和1两种状态,因此我们可以用bitset去优化。

    故整体的时间复杂度为 O(n2max(ai)64)mathcal{O}(frac{n^2max(a_i)}{64})

    代码:

    #include <bits/stdc++.h>
    #define maxn 30
    using namespace std;
    bitset<maxn>bit;
    typedef long long ll;
    int main()
    {
        int n;
        scanf("%d",&n);
        int sum=0;
        bit[0]=1;
        for(int i=1;i<=n;i++){
            int num;
            scanf("%d",&num);
            sum+=num;
            bit|=bit<<num;
        }
        int j=(sum+1)>>1;
        for(int i=j;i<=sum;i++){
            if(bit[i]){
                printf("%d
    ",i);
                return 0;
            }
        }
        return 0;
    }
    
  • 相关阅读:
    swig编译GDAL的C#库时遇到的代码安全问题及解决方法
    AE + GDAL实现影像按标准图幅分割(下)
    AE + GDAL实现影像按标准图幅分割(上)
    ArcEngine保存栅格数据至rastercatalog
    通过日志解决问题的一个小例子-http换端口
    firewall-cmd命令的富语言(richlanguage)示例
    VMware空虚拟机通过网络安装系统时获取不到IP地址情况(基于Linux的DHCP服务器)
    Linux中tune2fs命令的-o选项
    date -d
    tmp/ 和 var/tmp/ 的区别
  • 原文地址:https://www.cnblogs.com/Chen-Jr/p/11007139.html
Copyright © 2011-2022 走看看