• bzoj 3105


    感觉这题出得真好。

    我们将问题简化过后是这样的:

    给定一个数集,找一个最大的非空子集(一个集合的大小是它的元素和)A,使得A不存在一个非空子集,其所有元素的异或和为0。

    因为我们始终可以只选一个数,所以如果允许选空集,也没有选一个数优,所以我们将原来的问题变成:

    给定一个数集,找一个最大的子集(一个集合的大小是它的元素和)A,使得A不存在一个非空子集,其所有元素的异或和为0。

    我们定义拟阵(E,I),E为给定的数集,I的元素为所有满足“其所有元素异或和不为0”的集合加上空集。

    我们可以将每个数看成一个向量,每一维是0或1,即对应的位,”所有元素异或和不为0“等价于这个向量集合线性不相关,

    所以这是一个带权的向量拟阵。

    我们先将所有数从大到小排序,从前往后每次尝试加入一个数,能加则加,能加的判定标准是加入后和当前已经加入的数线性不相关(在GF(2)域下?),即加入后不存在一个子集,其异或和为0。

    判定是否存在一个子集异或和为0的方法具体看代码,有点类似高斯消元。

     1 /**************************************************************
     2     Problem: 3105
     3     User: idy002
     4     Language: C++
     5     Result: Accepted
     6     Time:8 ms
     7     Memory:1272 kb
     8 ****************************************************************/
     9  
    10 #include <cstdio>
    11 #include <iostream>
    12 #include <algorithm>
    13 #define N 110
    14 using namespace std;
    15  
    16 typedef long long dnt;
    17  
    18 int n;
    19 int aa[N], bb[N];
    20 int stk[N], top;
    21 dnt ans;
    22  
    23 bool ok() {
    24     for( int t=0; t<top; t++ ) 
    25         bb[t] = stk[t];
    26     for( int b=30,j=0; b>=0 && j<top; b-- ) {
    27         for( int k=j; k<top; k++ ) {
    28             if( (bb[k]>>b) & 1 ) {
    29                 swap(bb[k],bb[j]);
    30                 break;
    31             }
    32         }
    33         if( (bb[j]>>b) & 1 ) {
    34             for( int k=j+1; k<top; k++ )
    35                 if( (bb[k]>>b) & 1 ) {
    36                     bb[k] ^= bb[j];
    37                     if( bb[k]==0 ) return false;
    38                 }
    39             j++;
    40         }
    41     }
    42     return true;
    43 }
    44 int main() {
    45     scanf( "%d", &n );
    46     for( int i=0; i<n; i++ )
    47         scanf( "%d", aa+i );
    48     sort( aa, aa+n, greater<int>() );
    49     dnt ans = 0;
    50     for( int i=0; i<n; i++ ) {
    51         stk[top++] = aa[i];
    52         if( !ok() ) {
    53             top--;
    54             ans += aa[i];
    55         }
    56     }
    57     printf( "%lld
    ", ans );
    58 }
    59 
    View Code
  • 相关阅读:
    c# 自定义事件和委托
    C#委托之个人理解(转)
    invokeRequired属性和 invoke()方法
    .NET(C#)连接各类数据库
    Mobile Web Development with ASP.NET 2.0
    移动飞信WEB发送服务接口
    4行C#代码打造专业数据库连接配置界面
    domino 中 UniversalID 和NoteID的区别
    VB中preserve的用法
    LOTUS Note ID 剖析
  • 原文地址:https://www.cnblogs.com/idy002/p/4523349.html
Copyright © 2020-2023  润新知