zoukankan      html  css  js  c++  java
  • bzoj2460元素(线性基,贪心)

    题目大意:

    给定(n)个二元组((a,b)),求一个最大的(sum b)的集合,满足这个集合的任意子集的(a)(xor)值不为0

    这道题需要一个线性基的性质:
    线性基的任何非空子集的(xor)值不为0

    那么我们对于题目中对a的要求,只需要维护一个线性基即可。

    那如何保证(sum b)最大呢....我们可以按照b排序,然后依次插入线性基,如果经过插入操作后(a[i].a)不为0,就说明他被加入了线性基,那么就可以将他的(a[i].b)加入答案

    至于贪心的正确性....我也不是很会证明...大致可以理解为权值大的应该尽量早加,如果将当前点加入必须要删除之前的点的话,那一定是不优的,因为我们提前按照权值排过序

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #define ll long long
    
    using namespace std;
    
    inline ll read()
    {
      ll x=0,f=1;char ch=getchar();
      while (!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
      while (isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
      return x*f;
    }
    
    const int maxn = 110;
    
    ll base[maxn],n,k;
    struct Node{
    	ll id,val;
    };
    Node a[1010];
    ll ans;
    
    bool cmp (Node a,Node b)
    {
    	return a.val>b.val;
    }
    
    int main()
    {
      n=read();
      for (int i=1;i<=n;i++) a[i].id=read(),a[i].val=read();
      sort(a+1,a+1+n,cmp);
      for (int i=1;i<=n;i++)
      {
      	for (ll j=63;j>=0;j--)
      	{
      		if(a[i].id & (1LL << j))
      		{
      			if (!base[j])
      			{
      				base[j]=a[i].id;
      				break;
    			  }
    			a[i].id^=base[j];
    		  }
    	  }
    	if (a[i].id>0) ans+=a[i].val;
      }
      cout<<ans;
      return 0;
    }
    
    
  • 相关阅读:
    某耳机厂商微信公众平台建设方案
    微信公众号订单好评红包返现系统
    LNMP的配置与优化
    微信公众号用户OpenID同步导出系统
    微信公众号无限定时群发系统
    小程序想要什么
    微信支付默认推荐关注规则
    微信小程序(应用号)资源汇总整理
    微信公众平台小程序开发教程
    微信应用号开发教程
  • 原文地址:https://www.cnblogs.com/yimmortal/p/10160827.html
Copyright © 2011-2022 走看看