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;
    }
    
  • 相关阅读:
    程序员无休止加班的真正原因!
    Tomcat 爆出高危漏洞!
    Spring Boot 2.3 终于要来了!
    2020 年 4月全国程序员工资出炉!
    面试官再问你如何看待义务加班,学会如何怼回去!
    如何在一分钟内搞定面试官?
    安装android studio时,解决unable to access android sdk add-on list
    poj 3230 Travel(dp)
    hdu 2059 龟兔赛跑(dp)
    解决未能启动服务“VMware Authorization Service”
  • 原文地址:https://www.cnblogs.com/Chen-Jr/p/11007139.html
Copyright © 2011-2022 走看看