• 【清华集训2014】玛里苟斯


    UOJ36【清华集训2014】玛里苟斯

    给定序列 (a),每个元素有 (frac{1}{2}) 的概率被选择,设 (x) 表示被选择的元素的异或和,求 (x^k) 的期望。

    (nle 10^5,kle 5,a_ige 0)

    保证答案小于 (2^{63})

    Solution

    假设 (kge 3),那么可以注意到值域会大概是 (sqrt{2^{63}}) 这个级别。

    所以线性基很小,由于每种值的出现次数都相同(线性基的推论)所以每种值对答案的贡献都是 (frac{x^k}{2^{cnt}})

    否则如果 (k=1),那么只需要考虑每一位的贡献。

    (k=2) 就考虑一下每两位的贡献即可。

    当然,仍然只需要保留线性基的元素,这样的话就不会除非常大的数。

    然后这个题有结论,答案最多只能是 (x.5),所以特判一下即可

    (Code:)

    #include<bits/stdc++.h>
    using namespace std ;
    #define Next( i, x ) for( register int i = head[x]; i; i = e[i].next )
    #define rep( i, s, t ) for( register int i = (s); i <= (t); ++ i )
    #define drep( i, s, t ) for( register int i = (t); i >= (s); -- i )
    #define re register
    #define int __int128
    int gi() {
    	char cc = getchar() ; int cn = 0, flus = 1 ;
    	while( cc < '0' || cc > '9' ) {  if( cc == '-' ) flus = - flus ; cc = getchar() ; }
    	while( cc >= '0' && cc <= '9' )  cn = cn * 10 + cc - '0', cc = getchar() ;
    	return cn * flus ;
    }
    const int N = 1e5 + 5 ; 
    const int M = 100 + 5 ; 
    int n, K, cnt, tmp[M], s[M], C[M][M], fc[150] ;
    int Ans ; 
    void insert(int x) {
    	drep( i, 0, 64 ) if((x >> i) & 1) {
    		if( tmp[i] ) x ^= tmp[i] ;
    		else tmp[i] = x, x = 0 ;
    	}
    }
    int fpow(int x, int k) {
    	int ans = 1, base = x ;
    	while(k) {
    		if(k & 1) ans = ans * base ;
    		base = base * base, k >>= 1 ;
    	} return ans ;
    }
    void Dfs(int x, int S) {
    	if(x == cnt + 1) return Ans += fpow(S, K), void() ; 
    	Dfs(x + 1, S), Dfs(x + 1, S ^ s[x]) ;
    }
    void write() {
    	int iv = (1ll << cnt) ; 
    	int d = Ans / iv ; 
    	printf("%llu", (unsigned long long)(d) ) ;
    	if( d * iv < Ans ) printf(".5") ; 
    }
    void Solve1() {
    	Dfs(1, 0), write() ; 
    }
    void Solve2() {
    	fc[0] = 1 ; rep( i, 1, 100 ) fc[i] = fc[i - 1] * 2 ; 
    	rep( i, 0, 62 ) rep( j, 0, 62 ) {
    		if( i + j > 100 ) continue ; 
    		int a = 0, b = 0, c = 0, r = 0, d = fc[i + j] ;
    		rep( k, 1, cnt ) if((s[k] >> i) & 1) ++ a ;
    		rep( k, 1, cnt ) if((s[k] >> j) & 1) ++ b ;
    		rep( k, 1, cnt ) if(((s[k] >> i) & 1) && ((s[k] >> j) & 1)) ++ c ; 
    		a -= c, b -= c ; 
    		if( (!a) && (!c) && (!b) ) continue ;  
    		rep( k, 0, c ) {
    			int f = 0, g = 0 ;
    			if(k & 1) {
    				rep(l, 0, a) if(!(l & 1)) f += C[a][l] ;
    				rep(l, 0, b) if(!(l & 1)) g += C[b][l] ;
    				r += C[c][k] * f * g ; 
    			}
    			else {
    				rep(l, 0, a) if((l & 1)) f += C[a][l] ;
    				rep(l, 0, b) if((l & 1)) g += C[b][l] ;
    				r += C[c][k] * f * g ; 
    			}
    		} 
    		Ans += d * r * (1ll << (cnt - a - b - c)) ; 
    	} write() ; 
    }
    void Solve3() {
    	rep( j, 1, cnt ) Ans |= s[j] ;
    	cnt = 1 ; write() ; 
    }
    signed main()
    {
    	n = gi(), K = gi() ; int x ;
    	rep( i, 1, n ) x = gi(), insert(x) ; 
    	rep( i, 0, 64 ) if(tmp[i]) s[++ cnt] = tmp[i] ;
    	C[0][0] = 1 ; 
    	rep( i, 1, 64 ) rep( j, 0, 64 ) C[i][j] = (!j) ? 1 : (C[i - 1][j - 1] + C[i - 1][j]) ; 
    	if( K >= 3 ) Solve1() ; 
    	else if( K == 2 ) Solve2() ;
    	else Solve3() ; 
    	return 0 ;
    }
    
  • 相关阅读:
    文件拖拽上传
    30天自制操作系统笔记(第三天)
    PAT 1040到底有几个pat
    pat 1039 到底买不买
    pat 1038 统计同成绩学生
    pat 乙级1034
    pat 乙级1022
    pat 乙级1009
    pat 乙级1008
    pat 乙级1002
  • 原文地址:https://www.cnblogs.com/Soulist/p/13784372.html
Copyright © 2020-2023  润新知