zoukankan      html  css  js  c++  java
  • BZOJ3811 玛里苟斯(线性基+概率期望)

      k=1的话非常好做,每个有1的位都有一半可能性提供贡献。由组合数的一些性质非常容易证明。

      k=2的话,平方的式子展开可以发现要计算的是每一对位提供的贡献,于是需要计算每一对位被同时选中的概率。找出所有存在的相互绑定的位,这些位被同时选择的概率为0.5,而不被绑定的则为0.25。

      对于k>=3,其实用与k=1,2相同的方法大力讨论也可以做。考虑更优美的做法。有一个性质:集合内数相互异或不影响答案。证明比(bing)较(bu)显(hui)然(xie)。于是构造出线性基。可以发现线性基里的元素很少,暴搜一发即可。

      卡精度,不会证地有答案一定是整数或.5,全程整数各种乱搞即可。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define N 100010
    #define ll unsigned long long
    ll read()
    {
        ll x=0,f=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
        while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        return x*f;
    }
    int n,m,cnt=0;
    ll a[N],base[64],b[64];
    bool flag[64],f[64][64];
    ll ans,tot;
    void getbase()
    {
        for (int i=1;i<=n;i++)
        {
            ll x=a[i];
            for (int j=63;~j;j--)
            if (x&(1ll<<j))
                if (base[j]) x^=base[j];
                else {base[j]=x;break;}
        }
        for (int j=63;~j;j--)
        if (base[j]) b[++cnt]=base[j];
    }
    void solve1()
    {
        for (int i=1;i<64;i++) if (flag[i]) ans+=1ll<<i-1;
        cout<<ans;if (flag[0]) cout<<".5";
    }
    void solve2()
    {
        for (int i=0;i<34;i++)
            for (int j=0;j<34;j++)
            f[i][j]=1;
        for (int i=1;i<=n;i++)
            for (int j=0;j<34;j++)
                for (int k=j+1;k<34;k++) 
                if (((a[i]&(1ll<<j))>0)^((a[i]&(1ll<<k))>0)) f[j][k]=f[k][j]=0; 
        for (int i=0;i<34;i++)
        if (flag[i])
            for (int j=0;j<34;j++)
            if (flag[j])
            {
                if (!f[i][j]) ans+=(1ll<<i+j);
                else ans+=(2ll<<i+j);
                tot+=ans/4,ans%=4;
            }
        cout<<tot;if (ans) cout<<".5";
    }
    void solve3(int k,ll s)
    {
        if (k>cnt)
        {
            ll t=s*s*s;t/=(1<<cnt);for (int i=4;i<=m;i++) t*=s;tot+=t;
            t=s*s*s;t%=(1<<cnt);for (int i=4;i<=m;i++) t*=s;
            ans+=t;tot+=ans/(1<<cnt);ans%=(1<<cnt);
        }
        else solve3(k+1,s),solve3(k+1,s^b[k]);
    }
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("bzoj3811.in","r",stdin);
        freopen("bzoj3811.out","w",stdout);
        const char LL[]="%I64d
    ";
    #else
        const char LL[]="%lld
    ";
    #endif
        n=read(),m=read();
        for (int i=1;i<=n;i++)
        {
            a[i]=read();
            for (int j=0;j<64;j++) if (a[i]&(1ll<<j)) flag[j]=1;
        }
        if (m==1) solve1();
        if (m==2) solve2();
        if (m>=3)
        {
            getbase(),solve3(1,0);
            cout<<tot;if (ans) cout<<".5";
        }
        return 0;
    }
  • 相关阅读:
    实战练习6—水波纹制作
    实战练习5—冰块中的效果
    实战练习4—逼真眼泪
    5、选择工具&描边
    实战练习3-修饰服装皱褶
    实战练习2—方块
    实战练习1—照片的局部放大
    23、裁剪
    iOS 处理第三方SDK冲突问题
    iOS 修改启动图无效
  • 原文地址:https://www.cnblogs.com/Gloid/p/9741470.html
Copyright © 2011-2022 走看看