• BZOJ3811: 玛里苟斯


    $n leq 100000$个数问任选其一集合的集合元素异或值的$k,1 leq k leq 5$次方的期望。保证答案$<2^{63}$。

    这个数据范围有点坑爹。。

    $k=1$时,数字$<2^{63}$,考虑每一位的贡献。如果这一位全为0那么贡献为0,否则贡献一定为$frac{1}{2}*2^x$,$x$是当前数位。为啥呢,因为奇数个1和偶数个1的方案是一样多的。又为啥呢?组合数的奇数项和偶数项是一样多的。直接算。

    $k=2$时,数字$<2^{32}$,考虑一个答案,$(b_mb_{m-1}...b_1b_0)*(b_mb_{m-1}...b_1b_0)$,产生这样的贡献,括号拆开就是$sum_{i=0}^msum_{j=0}^mb_ib_j2^{i+j}$,如此。因此枚举两位,然后看这两位的状态。如果这两位上某一位全是0就贡献0;这两位的组合只有11或者00这两种,那贡献1/2;否则贡献1/4。用线性基判断。

    $k=3,4,5$时,数字$<2^21$,可以直接枚举线性基的所有组合。

    这个diao题很容易爆longlong,可以把答案用带分数表示,因为分母总是一样的。

      1 #include<iostream>
      2 #include<cstring>
      3 #include<cstdio>
      4 //#include<time.h>
      5 //#include<complex>
      6 //#include<set>
      7 //#include<queue>
      8 #include<algorithm>
      9 #include<stdlib.h>
     10 using namespace std;
     11 
     12 #define LL unsigned long long
     13 LL qread()
     14 {
     15     char c; LL s=0; while ((c=getchar())<'0' || c>'9');
     16     do s=s*10+c-'0'; while ((c=getchar())>='0' && c<='9'); return s;
     17 }
     18 
     19 //Pay attention to '-' , LL and double of qread!!!!
     20 
     21 int n,K;
     22 #define maxn 200011
     23 
     24 struct JI
     25 {
     26     LL a[66]; int n;
     27     void clear() {n=0; memset(a,0,sizeof(a));}
     28     void insert(LL v)
     29     {
     30         for (int i=63;~i && v;i--) if ((v>>i)&1)
     31         {
     32             if (!a[i]) {a[i]=v; n++; break;}
     33             v^=a[i];
     34         }
     35     }
     36     LL qmax()
     37     {
     38         LL ans=0;
     39         for (int i=63;~i;i--) ((ans^a[i])>ans) && (ans^=a[i]);
     40         return ans;
     41     }
     42     void rebuild()
     43     {
     44         for (int i=63;~i;i--)
     45             for (int j=i-1;~j;j--)
     46                 if ((a[i]>>j)&1) a[i]^=a[j];
     47     }
     48     LL p[66]; int lp;
     49     LL query(LL K)
     50     {
     51         lp=0; for (int i=0;i<=63;i++) if (a[i]) p[lp++]=a[i];
     52         if (K>=(1ll<<lp)) return -1;
     53         LL ans=0;
     54         for (int i=lp-1;~i;i--) if ((K>>i)&1) ans^=p[i];
     55         return ans;
     56     }
     57     LL qmax(LL v)
     58     {
     59         LL ans=v;
     60         for (int i=63;~i;i--) (((ans>>i)&1)==0 && (ans^=a[i]));
     61         return ans;
     62     }
     63 }ji;
     64 
     65 void solve1()
     66 {
     67     LL ans=0;
     68     for (int i=0;i<=63;i++)
     69     {
     70         bool flag=0;
     71         for (int j=0;j<=63;j++) if ((ji.a[j]>>i)&1) flag=1;
     72         if (flag) ans+=1ll<<i;
     73     }
     74     printf("%llu",(LL)(ans/2));
     75     if (ans&1) printf(".5");
     76 }
     77 
     78 void solve2()
     79 {
     80     LL ans=0,res=0;
     81     for (int i=0;i<=31;i++)
     82         for (int j=0;j<=31;j++)
     83         {
     84             bool c1,c2,c3,c4; c1=c2=c3=c4=0;
     85             for (int k=0;k<=31;k++)
     86             {
     87                 if (((ji.a[k]>>i)&1)==1 && ((ji.a[k]>>j)&1)==1) c1=1;
     88                 if (((ji.a[k]>>i)&1)==1 && ((ji.a[k]>>j)&1)==0) c2=1;
     89                 if (((ji.a[k]>>i)&1)==0 && ((ji.a[k]>>j)&1)==1) c3=1;
     90                 if (((ji.a[k]>>i)&1)==0 && ((ji.a[k]>>j)&1)==0) c4=1;
     91             }
     92             if (!(c1 || c3) || !(c1 || c2)) continue;
     93             if (!(c3 || c2))
     94             {
     95                 if (i+j>0) ans+=(1ll<<(i+j-1));
     96                 else res+=2;
     97             }
     98             else
     99             {
    100                 if (i+j>1) ans+=(1ll<<(i+j-2));
    101                 else res+=(1<<(i+j));
    102             }
    103         }
    104     printf("%llu",ans+(res>>2));
    105     if (res&3) printf(".5");
    106 }
    107 
    108 LL p[66]; int lp=0;
    109 void solve3()
    110 {
    111     for (int i=0;i<=63;i++) if (ji.a[i]) p[lp++]=ji.a[i];
    112     LL ans=0,res=0;
    113     for (int i=0;i<(1<<lp);i++)
    114     {
    115         LL now=0;
    116         for (int j=0;j<lp;j++) if ((i>>j)&1) now^=p[j];
    117         LL x=0,y=1;
    118         for (int j=0;j<K;j++)
    119         {
    120             x*=now; y*=now;
    121             x+=y>>lp; y=y&((1<<lp)-1);
    122         }
    123         res+=y; ans+=x;
    124     }
    125     printf("%llu",ans+(res>>lp));
    126     if (res&((1<<lp)-1)) printf(".5");
    127 }
    128 
    129 int main()
    130 {
    131     scanf("%d%d",&n,&K);
    132     for (int i=1;i<=n;i++) ji.insert(qread());
    133     ji.rebuild();
    134     if (K==1) solve1();
    135     else if (K==2) solve2();
    136     else solve3();
    137     return 0;
    138 }
    View Code
  • 相关阅读:
    PXC配置过程
    值得学习的C语言开源项目
    使用命令批量添加svn文件
    配置快捷键,自动最大化打开终端
    创建SpringBoot Starter教程
    SpringBoot说明文档使用技巧
    Windows MySQL8+安装教程
    字符串、常量池、StringBuilder之间的微妙关系
    Linux系统查看CPU、内存、硬盘命令
    cpu 使用率高问题定位及排查
  • 原文地址:https://www.cnblogs.com/Blue233333/p/8930885.html
Copyright © 2020-2023  润新知