分三种情况讨论
k=1时,对于每一位而言,只要有一个数这一位是1,那么这个就有0.5的概率是1,选他就是1,不选就是0,有第二个的话,在第一个选或不选的前提下,也各有0.5的几率选或不选,0和1的概率还是一半一半。所以无论有几个,只要有任意一个数该位不得0,期望就是(1<<i)/2。所以我们只需要把所有的或起来除以二即可。
k=2时,我们需要记录每两位之间的贡献,如果所有的数这两位都一样而且有都是1的数,那么这两位作出的贡献就是(1<<i+j)/2,
如果有不一样的,那么贡献就是(1<<i+j)/4,
k>=3时,我们发现现在的异或和最大是(1<<22),因为题目保证答案在(1<<63)内,所以我们状压直接暴力乱搞就好了,因为线性基的期望就是原数组的期望。然而我并不会理性证明,只能感性理解
1 #include2 #include 3 #include 4 #include 5 #include 6 #include 7 #define LL unsigned long long 8 #define N 100500 9 using namespace std;10 int n,m,p[66],bo[66];11 LL a[N],ANS,res;12 vector v;13 int main(){14 scanf("%d%d",&n,&m);15 for(int i=1;i<=n;i++)scanf("%llu",&a[i]);16 if(m==1){17 LL ans=0;18 for(int i=1;i<=n;i++)ans|=a[i];19 if(ans&1ll)printf("%llu.5\n",ans>>1ll);20 else printf("%llu\n",ans>>1ll);21 }22 else if(m==2){23 LL ans=0;24 for(int i=1;i<=n;i++)ans|=a[i];25 for(int i=0;i<=31;i++)if(ans&(1ll< >i)&1)!=((a[k]>>j)&1)){flag=1;break;}30 if(i+j-1-flag<0)res++;31 else ANS+=1ll< >1ll;res&=1ll;35 printf("%llu",ANS);36 if(res)printf(".5\n");37 }38 else{39 for(int i=1;i<=n;i++)40 for(int j=23;~j;j--)if(a[i]&(1ll< >nn);b&=(1ll< >nn;res&=(1ll<