• Codeforces1101G (Zero XOR Subset)-less 【线性基】【贪心】


    题目分析:

    考虑到这是一个区间的异或问题,不妨求出前缀和,令$sum[i] = Xor_{j=1}^{i}a[j]$。

    对于区间$[l,r]$的异或结果,等于$sum[r] oplus sum[l-1]$。那么原问题等价于选尽量多的点$p_x$,使得这些点构成的$sum[p_x] oplus sum[p_{x-1}]$的子集的异或非$0$。我们不断往前异或,可以把问题转化为选尽量多的$p_x$,使得$sum[p_x]$的子集的异或非$0$。这是因为这两者的线性基等价。

    这样子这题就变成BZOJ2460的弱化版了。关于BZOJ2460的证明,我还没想到。但是这道题是它的弱化版,也就是$magic=1$的情况,我可以试着给出一个证明。

    使用反证法,假设以不同的顺序插入线性基得到的答案是不同的,那么存在一种插入方式使得答案线性基为${a_i}$,另一种插入方式线性基为${b_i}$,$|{a_i}| > |{b_i}|$。现在只需说明$|{a_i}| = |{b_i}|$即可。

    实际上这里有一个想法,就是任意一种插入方式构成的线性基能表示出的数是相同的,就能说明$|{a_i}| = |{b_i}|$。为什么?

    想象一个二维空间和一个三维空间,坐标$(1,2,3)$不能在一个二维空间被表示不是吗?同理两个表示域相同的线性基的维度肯定相同,否则其中维度多的那个线性基的某一维肯定可以被其它维表示,这不符合线性基的定义。

    假设现在存在一个数$x$,$a$线性基可以表示,$b$线性基表示不了。如果这个数属于原序列,那么它一定早就被插入了$b$线性基中,而不会被忽视。否则它一定能被原序列中的几个数所表示出来。但我们又发现$b$线性基可以表示出原序列中的任何数,那么利用这些表示方法同样可以表示出$x$,所以这样的数不存在。所以$|{a_i}| = |{b_i}|$。

    代码:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 
     4 const int maxn = 205000;
     5 
     6 int n,a[maxn];
     7 
     8 int p[50];
     9 
    10 void read(){
    11     scanf("%d",&n);
    12     for(int i=1;i<=n;i++) scanf("%d",&a[i]),a[i] ^= a[i-1];
    13 }
    14 
    15 void work(){
    16     if(a[n] == 0){puts("-1");return;}
    17     for(int i=30;i>=0;i--)if(a[n] & (1<<i)) {p[i] = a[n];break;}
    18     int ans = 1;
    19     for(int i=1;i<n;i++){
    20     for(int j=30;j>=0;j--){
    21         if(a[i] & (1<<j)){
    22         if(p[j]) a[i] ^= p[j];
    23         else{p[j] = a[i];ans++;break;}
    24         }
    25     }
    26     }
    27     printf("%d
    ",ans);
    28 }
    29 
    30 int main(){
    31     read();
    32     work();
    33     return 0;
    34 }
  • 相关阅读:
    ASP.NET网站和ASP.NET应用程序的区别
    客户端状态的优缺点
    Web.config配置文件的优点
    ASP.NET中视图状态的优点和缺点
    java常见集合及其用途
    java Socket编程(一)
    java Soket编程(三)
    浏览器到服务器端进行通信的简单理解
    ant 常用命令
    切记,切忌!——转载(收藏以备用)
  • 原文地址:https://www.cnblogs.com/Menhera/p/10278098.html
Copyright © 2020-2023  润新知