BZOJ3811: 玛里苟斯
Posted Blue233333
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 }
以上是关于BZOJ3811: 玛里苟斯的主要内容,如果未能解决你的问题,请参考以下文章