zoukankan      html  css  js  c++  java
  • 【2019牛客多校第一场】XOR

    题意:

    给你一个集合A,里边有n个正整数,对于所有A的、满足集合内元素异或和为0的子集S,问你∑|S|

    n<=1e5,元素<=1e18

    首先可以转化问题,不求∑|S|,而是求每个元素属于子集数的和,也就是统计每个元素对答案的贡献

    (题解中说根据期望的线性?我不懂期望和这个有啥关系,但是并不影响理解)

    既然要求集合中的异或和,线性基就是针对这一类问题的一把好手

    先给A求一个基R

    对于没有被扔进R的元素,每一个元素对答案的贡献都是2^(n-|R|-1)

    因为对于每个元素,先把它选走,剩下的不在R中的元素就可以随便选(也可以都不选),然后基R中一定能找出对应的元素组合把它们搞成0

    为什么不用担心R中会有被选出元素相关的贡献没有统计?

    注意线性基的性质:基中元素所有子集异或和都不同,保证了不会存在多种从R中选元素的方案,使得和不在R中选的元素异或和为0

    接下来需要统计R基中元素对答案的贡献

    遍历R中的元素,把它拎出来,给剩下的n-1个元素建个基D

    如果被拎出来的元素还能插♂进基D,那就没救了,绝对异或不出0

    否则它对答案的贡献就是2^(n-|D|-1),理由同上,不在D中的其他元素可以随便选,而从D中选子集的方案唯一

    求基D可以加速,给n个元素中没在基R里的元素建个基B(这名字真鬼 = =)

    然后每次把扔掉一个元素的基R和B合并

    (线性基最好玩的地方就是用一个小集合代表一个大集合,还能保证不重复不遗漏)

    这题我一开始把R中元素拎出来的方法是直接从基R的数组里挑,这种方法是错误的,反例:

    7 8 6 8 9 8

    如果直接从基里挑会直接把7和6(的第2,3个二进制位)一起挑出来,6本来还可以提供个0110的,但是往基里一放就被7搞没了

    正确的姿势应该是开数组把进R基的元素存起来,然后在这个数组里挑出,剩下的重新进基

    经验总结:
    1.结构化程序设计很重要!之前开了3个数组,然后给每个数组都写个基,debug很难受

    用把数组当函数参数的操作就可以只写一套线性基操作,需要用哪个基当参数扔进去即可

    2.不要忘记对拍。包括看别人代码找自己错误的时候,有时候眼睛看不出来有啥问题,拍一拍就找到了

    写个对拍也没多费事

    代码:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<cstring>
     5 #include<cmath>
     6 using namespace std;
     7 #define LL long long
     8 LL rd(){LL z=0,mk=1;  char ch=getchar();
     9     while(ch<'0'||ch>'9'){if(ch=='-')mk=-1;  ch=getchar();}
    10     while(ch>='0'&&ch<='9'){z=(z<<3)+(z<<1)+ch-'0';  ch=getchar();}
    11     return z*mk;
    12 }
    13 int n;  LL a[110000];
    14 LL bssr[110],bssb[110],bssd[110];
    15 LL ans=0,mo=1000000007;
    16 bool flg[110000];
    17 LL q[110000],hd=0;
    18 bool ist(LL x,LL y[]){
    19     for(int i=63;i>=0;--i)if((LL)1<<i&x){
    20         if(!y[i]){
    21             y[i]=x;
    22             ++y[64];
    23             return true;
    24         }
    25         x^=y[i];
    26     }
    27     return false;
    28 }
    29 bool chck(LL x,LL y[]){
    30     for(int i=63;i>=0;--i)if((LL)1<<i&x)
    31         x^=y[i];
    32     return !x;
    33 }
    34 LL qcp(LL x,int y){
    35     LL z=1;
    36     for(;y;y>>=1){
    37         if(y&1)  z=(z*x)%mo;
    38         x=(x*x)%mo;
    39     }
    40     return z;
    41 }
    42 void prvs(){
    43     memset(bssr,0,sizeof(bssr));
    44     memset(bssb,0,sizeof(bssb));
    45     for(int i=1;i<=n;++i)  flg[i]=false;
    46     ans=0;
    47     hd=0;
    48     return ;
    49 }
    50 int main(){
    51     //freopen("ddd.in","r",stdin);
    52     //freopen("ddd.out","w",stdout);
    53     while(~scanf("%d",&n)){
    54         prvs();
    55         for(int i=1;i<=n;++i)  a[i]=rd();
    56         for(int i=1;i<=n;++i){
    57             flg[i]=ist(a[i],bssr);
    58             if(flg[i])  q[++hd]=a[i];
    59         }
    60         if(bssr[64]==n){
    61             printf("0\n");
    62             continue;
    63         }
    64         ans+=(n-bssr[64])*qcp(2,n-bssr[64]-1)%mo;
    65         for(int i=1;i<=n;++i)if(!flg[i])
    66             ist(a[i],bssb);
    67         /*for(int k=0;k<=63;++k)if(bssr[k]){
    68             memset(bssd,0,sizeof(bssd));
    69             for(int i=0;i<=63;++i)
    70                 if(i!=k)  bssd[i]=bssr[i];
    71             bssd[64]=bssr[64]-1;
    72             for(int i=0;i<=63;++i)if(bssb[i])
    73                 ist(bssb[i],bssd);
    74             if(chck(bssr[k],bssd))
    75                 ans=(ans+qcp(2,n-bssd[64]-1))%mo;
    76         }*/
    77         for(int k=1;k<=hd;++k){
    78             memset(bssd,0,sizeof(bssd));
    79             for(int i=1;i<=hd;++i)if(i!=k)
    80                 ist(q[i],bssd);
    81             for(int i=0;i<=63;++i)if(bssb[i])
    82                 ist(bssb[i],bssd);
    83             if(chck(q[k],bssd))
    84                 ans=(ans+qcp(2,n-bssd[64]-1))%mo;
    85         }
    86         printf("%lld\n",ans);
    87     }
    88     return 0;
    89 }
    View Code
  • 相关阅读:
    Visifire正式版(v1.1)发布
    [转]PSP机能强大!已能模拟运行WINDOWS系统?
    在Silverlight+WCF中应用以角色为基础的安全模式(一)基础篇之角色为基础的安全模式简介 Virus
    C#的加密解密算法,包括Silverlight的MD5算法 Virus
    MMORPG programming in Silverlight Tutorial (10)Implement the sprite’s 2D animation (Part IV)
    Game Script: Rescue Bill Gates
    MMORPG programming in Silverlight Tutorial (9)KeyFrame Animation
    MMORPG programming in Silverlight Tutorial (5)Implement the sprite’s 2D animation (Part II)
    MMORPG programming in Silverlight Tutorial (7)Perfect animation
    MMORPG programming in Silverlight Tutorial (3)Animate the object (Part III)
  • 原文地址:https://www.cnblogs.com/cdcq/p/11211836.html
Copyright © 2011-2022 走看看