zoukankan      html  css  js  c++  java
  • BZOJ3811: 玛里苟斯

    BZOJ3811: 玛里苟斯

    https://lydsy.com/JudgeOnline/problem.php?id=3811

    分析:

    • (K=1)可以随便做,每一位的贡献都是确定的,推一推可以发现每一位是(1)的概率都是(1/2),这是因为这位是(0)的数字对答案没有影响。直接把所有数或起来除(2)就可以。
    • (K>2)的情况最多有(21)位数字,我们感性理解一下可知所有能异或出来的数字的概率相同,建出线性基暴力枚举异或出的数字是什么即可。
    • (K=2)的情况需要推一推式子,这里有一篇很好的题解http://www.cnblogs.com/wangck/p/4187488.html

    代码:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cstdlib>
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    #define N 100050
    int n,K;
    ull a[N];
    namespace Cas1 {
    	int main() {
    		ull ans=0;
    		int i;
    		for(i=1;i<=n;i++) ans|=a[i];
    		printf("%llu",ans>>1);
    		if(ans&1) printf(".5");puts("");
    		return 0;
    	}
    }
    namespace Cas2 {
    	int main() {
    		ull mx=0,ans=0,re=0;
    		int i,j,k;
    		for(i=1;i<=n;i++) mx|=a[i];
    		for(i=62;i>=0;i--) {
    			for(j=62;j>=0;j--) {
    				if(!(mx>>i&1)||!(mx>>j&1)) continue;
    				int flg=1;
    				for(k=1;k<=n;k++) {
    					if(((a[k]>>i)&1)!=((a[k]>>j)&1)) {
    						flg=0; break;
    					}
    				}
    				if(flg) ans+=(1llu<<(i+j))/2,re+=(1llu<<(i+j))&1;
    				else ans+=(1llu<<(i+j))/4,re+=(1llu<<(i+j))%4>0;
    			}
    		}
    		printf("%llu",ans+re/2);
    		if(re&1) printf(".5"); puts("");
    		return 0;
    	}
    }
    namespace Cas3 {
    	ull b[100],c[100],ans,re;
    	int m;
    	void insert(ull x) {
    		int i;
    		for(i=22;i>=0;i--) if((x>>i)&1) {
    			if(b[i]) x^=b[i];
    			else {b[i]=x; return ;}
    		}
    	}
    	int main() {
    		int i,s;
    		for(i=1;i<=n;i++) insert(a[i]);
    		for(i=22;i>=0;i--) if(b[i]) c[++m]=b[i];
    		int mask=(1<<m)-1;
    		for(s=0;s<=mask;s++) {
    			ull val=0;
    			for(i=1;i<=m;i++) if(s&(1<<(i-1))) val^=c[i];
    			ull a=0,b=1;
    			for(i=1;i<=K;i++) {
    				a=a*val; b=b*val;
    				a+=b>>m; b&=mask;
    			}
    			ans+=a;
    			re+=b;
    			ans+=re>>m;
    			re&=mask;
    		}
    		printf("%llu",ans);
    		if(re) printf(".5");
    		puts("");
    		return 0;
    	}
    }
    int main() {
    	scanf("%d%d",&n,&K);
    	int i;
    	for(i=1;i<=n;i++) {
    		scanf("%llu",&a[i]);
    	}
    	if(K==1) {
    		return Cas1::main();
    	}else if(K==2) {
    		return Cas2::main();
    	}else {
    		return Cas3::main();
    	}
    }
    
  • 相关阅读:
    【HTML5】元素<script>与<noscript>的使用
    【HTML5】元素<head>的使用
    【HTML5】交互元素menu&command元素
    【HTML5】summary交互元素
    【HTML5】用脚本控制交互元素details元素的使用
    【BIEE】页面跳转以及跳转后返回
    (C语言版)链表(三)——实现双向链表创建、删除、插入、释放内存等简单操作
    哪些年是闰年
    工程师职称评定条件
    linux 网络编程-基础篇01
  • 原文地址:https://www.cnblogs.com/suika/p/10264093.html
Copyright © 2011-2022 走看看