• [BJWC2011]元素


    题目

      点这里看题目。

    分析

      如果称(Magic)为权,(Number)为值,我们需要求的是一个异或意义下,值线性不相关而且权的和最大的问题,也就是权值之和最大的极大线性无关组。
      看到这个形式的问题,我们就可以考虑向拟阵的方向去靠一靠了。
      设(S={Number_i}, I={x:xsubseteq S, ext{x的任意非空子集是线性无关的}})
      考虑(<S,I>)是否为一个子集系统:
      遗传性:假如有(Bin I),则对于任意一个非空(Asubseteq B),由于(B)的任意非空子集线性无关,所以(A)的任意非空子集也是线性无关的,因此(Ain I),证毕。
      考虑(<S,I>)是否为一个拟阵:
      交换性:设(A,Bin I,|A|<|B|),我们要证明,(exists xin B-A, Acup {x}in I)
      反证法,即假设对于任意(xin B-A),都不满足(Acup {x}in I)。这说明这样的(x)全在(A)的线性空间中(即都可以用(A)中的异或出来)。因此(B)的元素全在(A)的线性空间中,因此(B)的线性空间包含在(A)的线性空间中。由于(|A|<|B|),且(A)(B)各自的任意非空子集都是线性无关的,因此矛盾。因此存在交换律,证毕。


      说了这么多我觉得大家也不太想看。
      简单来说,我们就可以直接按照拟阵的贪心思路,维护一个线性无关组(A),将矿石按照(Magic)从大到小在保证线性无关的前提下尝试着插入到(A),如果可以插入就可以计入答案。线性无关组可以用线性基来维护,因此时间是(O(nlog_2n +nlog_2 Number_{max}))

    代码

    #include <cstdio>
    #include <algorithm>
    using namespace std;
    
    typedef long long LL;
    
    const int MAXN = 1005, MAXLOG = 70;
    
    template<typename _T>
    void read( _T &x )
    {
    	x = 0;char s = getchar();int f = 1;
    	while( s > '9' || s < '0' ){if( s == '-' ) f = -1; s = getchar();}
    	while( s >= '0' && s <= '9' ){x = ( x << 3 ) + ( x << 1 ) + ( s - '0' ), s = getchar();}
    	x *= f;
    }
    
    template<typename _T>
    void write( _T x )
    {
    	if( x < 0 ){ putchar( '-' ); x = ( ~ x ) + 1; }
    	if( 9 < x ){ write( x / 10 ); }
    	putchar( x % 10 + '0' );
    }
    
    struct element
    {
    	LL num; int mag;
    	element() { num = mag = 0; }
    	bool operator < ( const element & b ) const { return mag > b.mag; }
    }a[MAXN];
    
    LL base[MAXLOG];
    int N;
    
    void insert( LL v )
    {
    	for( int j = 60 ; ~ j ; j -- )
    		if( v >> j & 1 )
    		{
    			if( ! base[j] ) { base[j] = v; break; }
    			v ^= base[j];
    		}
    }
    
    bool chk( LL v )
    {
    	for( int j = 60 ; ~ j ; j -- )
    		if( v >> j & 1 )
    			v ^= base[j];
    	return ! v;
    }
    
    int main()
    {
    	read( N );
    	for( int i = 1 ; i <= N ; i ++ ) read( a[i].num ), read( a[i].mag );
    	std :: sort( a + 1, a + 1 + N );
    	int ans = 0;
    	for( int i = 1 ; i <= N ; i ++ ) if( ! chk( a[i].num ) ) ans += a[i].mag, insert( a[i].num );
    	write( ans ), putchar( '
    ' );
    	return 0;
    }
    
  • 相关阅读:
    java攻城狮之路(Android篇)--widget_webview_metadata_popupwindow_tabhost_分页加载数据_菜单
    java攻城狮之路(Android篇)--MP3 MP4、拍照、国际化、样式主题、图片移动和缩放
    java攻城狮之路(Android篇)--BroadcastReceiver&Service
    内存调试的东西D/dalvikvm( 809 ): GC_CONCURRENT freed
    java攻城狮之路(Android篇)--Activity生命
    java攻城狮之路(Android篇)--与服务器交互
    java实例练习
    java攻城狮之路(Android篇)--ListView与ContentProvider
    java攻城狮之路(Android篇)--SQLite
    Android中使用自身携带的Junit新建一个测试工程
  • 原文地址:https://www.cnblogs.com/crashed/p/12694812.html
Copyright © 2020-2023  润新知