生活随笔
收集整理的這篇文章主要介紹了
【清华集训2014】【BZOJ3811】玛里苟斯
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
Description
魔法之龍瑪里茍斯最近在為加基森拍賣師的削弱而感到傷心,于是他想了一道數學題。
S 是一個可重集合,S={a1,a2,…,an}。
等概率隨機取 S 的一個子集 A={ai1,…,aim}。
計算出 A 中所有元素異或 x, 求 xk 的期望。
Input
第一行兩個正整數 n, k。
以下 n 行每行一個整數,表示 ai。
Output
如果結果是整數,直接輸出。如果結果是小數(顯然這個小數是有限的),輸出精確值(末尾不加多余的 0)。
Sample Input
4 2
0
1
2
3
Sample Output
3.5
HINT
限制與約定
1≤n≤100000,1≤k≤5,ai≥0。最終答案小于 2^63 。k=1,2,3,4,5 各自占用 20% 的數據
Source
2015年國家集訓隊測試
感覺這個題是清華集訓2014Day1三個題里最難的..
看上去一臉不可做,實際上也確實是一臉不可做..
自己想只會做k=1的..按位統計每位的異或期望值..
安利兩個很好的題解.
題解1
題解2
結合起來看,看了一上午,最后看懂了…
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define MAXN 100010
#define LL unsigned long long
#define GET (ch>='0'&&ch<='9')
using namespace std;
int n,k,top;
LL a[MAXN],b[MAXN],ans1,ans2;
inline void in(LL &x)
{
char ch=getchar();x=
0;
while (!GET) ch=getchar();
while (GET) x=x*
10+ch-
'0',ch=getchar();
}
void dfs(
int x,LL sum)
{
if (x>top){LL sum1=
0,sum2=
1;
for (
int i=
1;i<=k;i++) sum1*=sum,sum2*=sum,sum1+=(sum2>>top),sum2&=((
1<<top)-
1);ans1+=sum1;ans2+=sum2;ans1+=(ans2>>top);ans2&=((
1<<top)-
1);
return;}dfs(x+
1,sum);dfs(x+
1,sum^a[x]);
}
int main()
{
scanf(
"%d%d",&n,&k);
for (
int i=
1;i<=n;i++) in(a[i]);
if (k==
1){
for (
int i=
1;i<=n;i++) ans1|=a[i];
return printf(ans1&
1?
"%llu.5\n":
"%llu\n",ans1>>
1),
0;}
if (k==
2){top=
1;
for (
int i=
1;i<=n;i++) b[
1]|=a[i];
for (
int i=
1;i<=n;i++)
for (
int j=
1;j<=top;++j){
if (!(b[j]&(~a[i])))
continue;
if (!(b[j]&a[i]))
continue;b[++top]=b[j]&a[i];b[j]&=~a[i];}
for (
int i=
1;i<=top;i++)
for (
int j=i;j<=top;j++) ans1+=b[i]*b[j];
return printf(ans1&
1?
"%llu.5\n":
"%llu\n",ans1>>
1),
0;}
for (
int i=(
1<<
22);i;i>>=
1){
int j=top+
1;
for (;j<=n;j++)
if (a[j]&i)
break;
if (j>n)
continue;swap(a[j],a[++top]);
for (j=
1;j<=n;j++)
if (j!=top&&(a[j]&i)) a[j]^=a[top];}dfs(
1,
0);
printf(ans2?
"%llu.5\n":
"%llu\n",ans1);
}
總結
以上是生活随笔為你收集整理的【清华集训2014】【BZOJ3811】玛里苟斯的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。