zoukankan      html  css  js  c++  java
  • UOJ #36「清华集训2014」玛里苟斯

    这怎么想得到啊.........

    UOJ #36

    题意:求随机一个集合的子集的异或和的$k$次方的期望值,保证答案$ lt 2^{63},1 leq k leq 5$


    $ Solution:$

    首先考虑$ k=1$的时候怎么做:如果某位上有$ 1$则有$ frac{1}{2}$的概率可以取到这一位

    $ k=1$时每一位都是独立的,可以直接做

    然后考虑$ k=2$时怎么做

    如果一个集合中有元素$ a,b$,则产生的贡献为$ a^2+2ab+b^2$

    我们把$ a^2$和$2ab$分开讨论

    如果某位有$ 1$,则有$ frac{1}{4}$的概率取到$ a^2$

    如果某两个不同的位均有$ 1$,则有$ frac{1}{4}$的概率取到$ 2ab$

    注意如果这两个不同的位只能一起被取,这个概率将被改成$ frac{1}{2}$

    然后考虑$ 3 leq k leq 5$时怎么做

    发现产生任何一个能够被原集合的若干个数异或和表示的数都是等概率

    因此我们只需要保留原集合的线性基即可

    由于答案$ lt 2^{63}$,能产生的最大的数并不大,大约为$ sqrt[k]{2^{63}}$级别

    因此能表示出的数的数量大致也是这个级别的

    建出线性基之后爆搜每个数并统计答案

    注意中间计算过程中可能会爆$ long long$可能需要手写压位或$int128$


     $ my code(int128)$

    #include<ctime>
    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<queue>
    #define rt register int
    #define ll long long
    using namespace std;
    inline ll read(){
        ll x = 0; char zf = 1; char ch = getchar();
        while (ch != '-' && !isdigit(ch)) ch = getchar();
        if (ch == '-') zf = -1, ch = getchar();
        while (isdigit(ch)) x = x * 10 + ch - '0', ch = getchar(); return x * zf;
    }
    void write(ll y){if(y<0)putchar('-'),y=-y;if(y>9)write(y/10);putchar(y%10+48);}
    void writeln(const ll y){write(y);putchar('
    ');}
    int i,j,k,m,n,x,y,z;unsigned ll cnt,c[65],a[65];
    namespace subtask1{
        bool b[65];
        void main(){
            ll ans=0;
            for(rt i=1;i<=n;i++)for(rt j=0;j<=63;j++)if(a[i]>>j&1)b[j]=1;
            for(rt j=0;j<=63;j++)if(b[j])cnt+=(unsigned ll)1<<j;
            cout<<(cnt/2);if(cnt%2)cout<<".5";
        }
    }
    namespace subtask2{
        bool b1[65][65],b2[65][65],b[65];
        void main(){
            __int128 ans=0;
            for(rt i=1;i<=n;i++)
            for(rt j=0;j<=63;j++)
            for(rt k=0;k<=63;k++)if(j!=k){
                if(a[i]>>j&1){
                    if(a[i]>>k&1)b1[j][k]=1;else b2[j][k]=1;
                    b[j]=1;
                }
            }
            for(rt i=0;i<=63;i++)
            for(rt j=i+1;j<=63;j++){
                __int128 all=0;
                if(b1[i][j])all=2;
                if(b1[i][j]&&(b2[i][j]||b2[j][i]))all=1;
                if(b2[i][j]&&b2[j][i])all=1;
                if(all)
                ans+=all*2*(1ll<<i)*(1ll<<j);
            }
            for(rt i=0;i<=63;i++)if(b[i])ans+=(unsigned ll)2*(1ll<<i)*(1ll<<i);
            ans/=2;write(ans/2);
            if(ans&1)cout<<".5";
        }
    }
    namespace subtask3{
        __int128 ans;
        __int128 mi(__int128 x,int y){
            __int128 ans=1;
            for(rt i=1;i<=y;i++)ans*=x;
            return ans;
        }
        void dfs(int x,__int128 y){
            if(x>n){
                ans+=mi(y,m);
                return;
            }
            dfs(x+1,y);dfs(x+1,y^a[x]);
        }
        void main(){
            ans=0;dfs(1,0);
            for(rt i=1;i<n;i++)ans/=2;
            write(ans/2);if(ans&1)cout<<".5";
        }
    } 
    int main(){
        n=read();m=read();
        for(rt i=1;i<=n;i++){
            ll x=read();
            for(rt j=63;j>=0;j--)if(x>>j&1){
                if(c[j])x^=c[j];
                else {
                    c[j]=x;
                    break;
                }
            }
        }
        n=0;
        for(rt i=0;i<=63;i++)if(c[i])a[++n]=c[i];
        if(m==1)subtask1::main();
        if(m==2)subtask2::main();
        if(m>=3)subtask3::main();
        return 0;
    }
  • 相关阅读:
    HUD——T 3836 Equivalent Sets
    HDU——T 2594 Simpsons’ Hidden Talents
    vertical-align和line-height的深入应用
    November 7th 2016 Week 46th Monday
    November 6th 2016 Week 46th Sunday
    November 5th Week 45th Saturday 2016
    November 4th Week 45th Friday 2016
    【2017-01-08】QTimer与QThread的调度时间精度
    November 3rd Week 45th Thursday 2016
    November 2nd Week 45th Wednesday 2016
  • 原文地址:https://www.cnblogs.com/DreamlessDreams/p/10062049.html
Copyright © 2011-2022 走看看