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}^m\sum_{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

 

posted @ 2018-04-24 15:22  Blue233333  阅读(171)  评论(0编辑  收藏  举报