玛里苟斯[清华集训2014 Day1]

玛里苟斯[清华集训2014 Day1]

魔法之龙玛里苟斯最近在为加基森拍卖师的削弱而感到伤心,于是他想了一道数学题。

S 是一个可重集合,S={a1,a2,,an}

等概率随机取 S 的一个子集 A={ai1,,aim}

计算出 A 中所有元素异或 x, 求 xk 的期望。

SOL :

这题目太色情了。没打高精度炸的不要不要的。

 我们观察一波局势,发现当K=1时我们可以按位异或,我们可以证明,若 S集合中存在X 在 i位是1,那么这一位上出现1的期望就是0.5.

  证明如下,我们把每一位上的ai的值取出来,那么我们发现0对答案没有贡献。设我们有X个1,而我们取偶数个1的期望为 signma C(2i+1,x)=((1+1)^n+(1-1) ^ n)/2;

而总数为2^n,那么我们的期望就是0.5.

所以我们统计每一位上是否有1,最后累加除2.

K=2:我们依旧统计每一位上是否有1.

 我们发现我们得到每一位上有1的位对答案

   ∑j=0mp=0m(2ni=1bi,jbi,p2n2j+p)

我们就可以将其答案统计出来。

K>2 我们惊奇的发现,对S其进行求线性基其答案不变。我们发现K>2时由于答案在LongLong范围内,我们可以保证求出得基最多22个,

暴力统计答案即可。

#pragma optimize("-O2")
#include<bits/stdc++.h>
#define sight(c) ('0'<=c&&c<='9')
#define LL unsigned long long
#define N 100009
#define db long double
const LL mo=(1<<25)-1;
using namespace std;
struct NL{
    LL a,b;
    NL() {a=b=0;}
    NL(LL x,LL y):a(x),b(y){}
    inline NL operator ^(const NL &A)const &{
       return NL(A.a^a,A.b^b);
    }
    inline NL operator ^(const LL &A)const &{
       return NL(a,A^b);
    }
    inline NL operator +(const NL &A)const &{
       NL T;
       T.a=A.a+a; T.b=A.b+b;
       if (T.b>mo) T.a+=T.b>>25,T.b&=mo;
       return T;
    }
    inline NL operator +(const LL &A)const &{
       NL T; T.a=a; T.b=A+b;
       if (T.b>mo) T.a+=T.b>>25,T.b&=mo;
       return T;
    }
    inline NL operator *(const NL &A)const &{
       NL T;
       T.a=(A.a*a<<25)+A.a*b+A.b*a; T.b=A.b*b;
       if (T.b>mo) T.a+=T.b>>25,T.b&=mo;
       return T;
    }
    inline NL operator *(const LL &A)const &{
       NL T;
       T.a=a*A; T.b=A*b;
       if (T.b>mo) T.a+=T.b>>25,T.b&=mo;
       return T;
    }
    inline LL ok(int x){
        LL T=b&(1ll<<x)-1;
        b>>=x; b|=(a&(1ll<<x)-1)<<(25-x);a>>=x;
        return T;
    }
};
inline void read(LL &x){
    static char c;
    for (c=getchar();!sight(c);c=getchar());
    for (x=0;sight(c);c=getchar()) x=x*10+c-48;
}
void write(LL x) {
    if (x<10) { putchar('0'+x); return;} write(x/10); putchar('0'+x%10);
}
inline void writeln(LL x) {
    if (x<0) putchar('-'),x*=-1; write(x); putchar('\n');
}
LL n,k,ans,X,A[N],P[65],r,OT[65],O;
NL Ans;
void Guass()
{
    for (int i=1;i<=n;i++)
     for (int j=62;~j;j--)
        if ((A[i]>>j)&1) 
         if (!P[j]) {P[j]=A[i]; break;} 
         else A[i]^=P[j];
    for (int j=0;j<=62;j++) if (P[j]) OT[r++]=P[j];
}
int b[79];
inline NL pow(NL x,int k){
    NL anw=NL(0,1);
    for (;k;k>>=1,x=x*x)if (k&1) anw=anw*x;
    return anw;
}
void dfs(NL x,int t){
    if (!(t^r)) { Ans=Ans+pow(x,k); return;} 
    dfs(x^OT[t],t+1);  dfs(x,t+1);
}
int main () {    
    freopen("malygos.in","r",stdin);
    freopen("malygos.out","w",stdout);
    read(n); read(k);
    for (int i=1;i<=n;i++) {
      read(A[i]); 
      for (int j=0;j<=63;j++) b[j]|=(A[i]>>j)&1;
    }
    if (k==1) {
      for (int j=63;~j;j--) if (b[j]) ans+=1ll<<j; 
       write(ans>>1); if (ans&1) puts(".5\n"); return 0;
    }
    if (k==2) {
        for (int j=31;~j;j--) if (b[j]) Ans=Ans+(1ull<<2*j+1);
        for (int i=31;~i;i--) {
        for (int j=0;j<i;j++) {
            int c[4]={};
            for (int k=1;k<=n;k++)  c[(A[k]>>i&1)<<1|(A[k]>>j&1)]=1;
            for (int k=0;k<4;k++) 
                for (int ii=0;ii<4;ii++) 
                    for (int jj=0;jj<4;jj++) if (c[ii]&&c[jj])  c[ii^jj] = 1;
            int s=0;
            for (int k=0;k<4;k++) s+=c[k];
            if (c[3])     Ans=Ans+((LL)(8/s)*(1ULL<<i+j));
        }}
        LL g=Ans.ok(2);
        LL T=(Ans.a<<25)+Ans.b;
        write(T);
        LL MM=1<<2;
        if (g) {
            putchar('.');
            while (g) {g*=10; putchar('0'+g/MM); g%=MM;}
        }
        return 0;
    }
    Guass();
    dfs(NL(0,0),0);
    LL g=Ans.ok(r);
    LL T=(Ans.a<<25)+Ans.b;
    write(T);
    LL MM=1<<r;
    if (g) {
        putchar('.');
        while (g) {
            g*=10; putchar('0'+g/MM); g%=MM;}
    }
    return 0;
}

 

posted @ 2018-01-10 19:44  泪寒之雪  阅读(449)  评论(0编辑  收藏  举报