【BZOJ3811】玛里苟斯(线性基)

题面

BZOJ

题解

\(K=1\)很容易吧,拆位考虑贡献,所有存在的位出现的概率都是\(0.5\),所以答案就是所有数或起来的结果除二。

\(K=2\)的情况,我们直接拆开平方式,平方项的贡献直接算,出现的概率还是\(0.5\),然后\(2ab\)这样子的东西出现的概率是\(0.5*0.5=0.25\),然而注意到有一些位直接两两之间存在联系,即选择了第\(i\)位的时候必定会同时选择第\(j\)位,那么此时两位之间的概率就是\(0.5\),这一部分要特殊判断一下。

接下来考虑\(K\ge 3\)的情况。因为答案不会超过\(2^{63}\),所以任何一个数字都不会从超过\(2^{22}\)。我们知道如果一个数可以被线性基中的其他所有数给表示出来,那么这个数出现的概率一定是\(1/{2^{|G|}}\),其中\(|G|\)是线性基内的元素个数。既然数字大小不大,那么线性基中的元素个数也不多,所以可以构建线性基之后直接\(2^{|G|}\)枚举所有可能出现的数字,\(K\)次方之后求和即可。

注意一下,最终答案除掉总的数字个数之后在\(2^{63}\)以内,那么在除之前是可能爆掉的,所以这里可以拆位什么的存一下就好了。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
#define ll long long
#define ull unsigned long long
inline ull read()
{
ull x=0;bool t=false;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=true,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return t?-x:x;
}
int n,K;ull a[100100];
namespace Task1
{
void Solve()
{
ull ans=0;
for(int i=1;i<=n;++i)ans|=a[i];
if(ans&1)printf("%llu.5\n",ans>>1);
else printf("%llu\n",ans>>1);
}
}
namespace Task2
{
bool vis[50];
bool check(int x,int y)
{
if(!vis[x]||!vis[y])return false;
for(int i=1;i<=n;++i)
{
if((a[i]&(1ll<<x))&&!(a[i]&(1ll<<y)))return false;
if((a[i]&(1ll<<y))&&!(a[i]&(1ll<<x)))return false;
}
return true;
}
void Solve()
{
ull ans=0;
for(int i=0;i<33;++i)
for(int j=1;j<=n;++j)
if(a[j]&(1ll<<i)){vis[i]=true;break;}
for(int i=0;i<33;++i)if(vis[i])ans+=1ll<<(i+i);
for(int i=0;i<33;++i)
for(int j=i+1;j<33;++j)
if(vis[i]&&vis[j])ans+=1ll<<(i+j);
for(int i=0;i<33;++i)
for(int j=i+1;j<33;++j)
if(check(i,j))ans+=1ll<<(i+j);
if(ans&1)printf("%llu.5\n",ans>>1);
else printf("%llu\n",ans>>1);
}
}
namespace Task3
{
int p[50];
void insert(int x)
{
for(int i=30;~i;--i)
if(x&(1<<i))
{
if(!p[i]){p[i]=x;return;}
x^=p[i];
}
}
int S[55],top;
ull ans=0,r=0;
void Calc(int val)
{
int MOD=1<<top;
ull D=0,R=1;
for(int i=1;i<=K;++i)
{
D*=val;R*=val;
D+=R/MOD;R%=MOD;
}
ans+=D;r+=R;
ans+=r/MOD;r%=MOD;
}
void dfs(int x,int val)
{
if(x==top+1){Calc(val);return;}
dfs(x+1,val);dfs(x+1,val^S[x]);
}
void Solve()
{
for(int i=1;i<=n;++i)insert(a[i]);
for(int i=0;i<=30;++i)if(p[i])S[++top]=p[i];
dfs(1,0);
if(r)printf("%llu.5\n",ans);
else printf("%llu\n",ans);
return;
}
}
int main()
{
n=read(),K=read();
for(int i=1;i<=n;++i)a[i]=read();
if(K==1){Task1::Solve();return 0;}
if(K==2){Task2::Solve();return 0;}
if(K>=3){Task3::Solve();return 0;}
return 0;
}

【BZOJ3811】玛里苟斯(线性基)的更多相关文章

  1. UOJ#36. 【清华集训2014】玛里苟斯 线性基

    原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ36.html 题解 按照 $k$ 分类讨论: k=1 : 我们考虑每一位的贡献.若有至少一个数第 $i$ ...

  2. BZOJ.3811.玛里苟斯(线性基)

    BZOJ UOJ 感觉网上大部分题解对我这种数学基础差的人来说十分不友好...(虽然理解后也觉得没有那么难) 结合两篇写的比较好的详细写一写.如果有错要指出啊QAQ https://blog.csdn ...

  3. [清华集训2015 Day1]玛里苟斯-[线性基]

    Description Solution 考虑k=1的情况.假设所有数中,第i位为1的数的个数为x,则最后所有的子集异或结果中,第i位为1的个数为$(C_{k}^{1}+C_{k}^{3}+...)$ ...

  4. BZOJ3811 玛里苟斯(线性基+概率期望)

    k=1的话非常好做,每个有1的位都有一半可能性提供贡献.由组合数的一些性质非常容易证明. k=2的话,平方的式子展开可以发现要计算的是每一对位提供的贡献,于是需要计算每一对位被同时选中的概率.找出所有 ...

  5. 【BZOJ 3811】玛里苟斯 大力观察+期望概率dp+线性基

    大力观察:I.从输出精准位数的约束来观察,一定会有猫腻,然后仔细想一想,就会发现输出的时候小数点后面不是.5就是没有 II.从最后答案小于2^63可以看出当k大于等于3的时候就可以直接搜索了 期望概率 ...

  6. uoj#36. 【清华集训2014】玛里苟斯(线性基+概率期望)

    传送门 为啥在我看来完全不知道为什么的在大佬们看来全都是显然-- 考虑\(k=1\)的情况,如果序列中有某一个\(a_j\)的第\(i\)位为\(1\),那么\(x\)的第\(i\)位为\(1\)的概 ...

  7. bzoj 3811: 玛里苟斯【线性基+期望dp】

    这个输出可是有点恶心啊--WA*inf,最后抄了别人的输出方法orz 还有注意会爆long long,要开unsigned long long 对于k==1,单独考虑每一位i,如果这一位为1则有0.5 ...

  8. UOJ #36 -【清华集训2014】玛里苟斯(线性基+暴搜)

    UOJ 题面传送门 看到 \(k\) 次方的期望可以很自然地想到利用低次方和维护高次方和的套路进行处理,不过.由于这里的 \(k\) 达到 \(5\),直接这么处理一来繁琐,二来会爆 long lon ...

  9. 洛谷P3389 高斯消元 / 高斯消元+线性基学习笔记

    高斯消元 其实开始只是想搞下线性基,,,后来发现线性基和高斯消元的关系挺密切就一块儿在这儿写了好了QwQ 先港高斯消元趴? 这个算法并不难理解啊?就会矩阵运算就过去了鸭,,, 算了都专门为此写个题解还 ...

随机推荐

  1. C# 多线程 Parallel.For 和 For 谁的效率高?那么 Parallel.ForEach 和 ForEach 呢?

    还是那句话:十年河东,十年河西,莫欺少年穷. 今天和大家探讨一个问题:Parallel.For 和 For 谁的效率高呢? 从CPU使用方面而言,Parallel.For 属于多线程范畴,可以开辟多个 ...

  2. Spring Aop: 关于继承和execution target this @annotation

    1.多态 target指通过这个对象调用的方法   (匹配标识对象的所有方法)  getMethod() this指调用这个对象的方法 (匹配标识对象实现的方法) getDeclaredMethod( ...

  3. core_cm4_simd.h文件是干嘛的?

    core_cm4_simd.h文件用于simd指令,即单指令多数据流,这个只有ARMv7架构才有,Cortex m3 m4 m7是ARMv7架构,而Cortex m0 m1是没有的. 所以,在新建Co ...

  4. GNU构建系统和AutoTools

    注:本篇博客是阅读文末[参考博客]的讲解所写,内容非原创,仅是学习笔记 1. 概述2. 不同视角的程序构建2.1 用户视角2.2 开发者视角3. 导图图片4. configure选项参考博客 1. 概 ...

  5. HDU 3537 Daizhenyang's Coin

    链接 [http://acm.hdu.edu.cn/showproblem.php?pid=3537] 题意 题意:已知一排硬币中有n个硬币正面朝上,输入正面朝上的硬币的位置ai.两人轮流操作, 每次 ...

  6. 第二次作业 对VC++6.0编译软件的评价

    首先这个软件伴随着我们很长时间了,它是我们一上大学最先接触的,也是应用相当多的一个软件,其实在最初的时候,我对编译软件的理解非常有限,觉得它能实现一个代码的功能十分神奇的一件事情,虽然彼时我们写的代码 ...

  7. Scrum Meeting NO.10

    Scrum Meeting No.10 1.会议内容 2.任务清单 徐越 序号 近期的任务 进行中 已完成 1 "我"回答过的问题 -- 界面 √ 2 "问题" ...

  8. 第八周--Linux中进程调度与进程切换的过程

    [潘恒 原创作品转载请注明出处 <Linux内核分析>MOOC课程 "http://mooc.study.163.com/course/USTC 1000029000 " ...

  9. 20135337——Linux内核分析:第十七章 模块与设备

    第17章 模块与设备 设备类型:在所有 Unix 系统中为了统一普通设备的操作所采用的分类. 模块: Linux 内核中用于按需加载和卸载目标码的机制. 内核对象:内核数据结构中支持面向对象的简单操作 ...

  10. 第三个Sprint冲刺第五天(燃尽图)