[HAOI2015]按位或
阿新 • • 發佈:2018-10-03
const can tdi base 如何 rand long pac return 容斥,我們知道
\[\max\{S\}=\sum_{T\subseteq S}(-1)^{|T|+1}\times \min\{T\}\]
description
洛谷
剛開始你有一個數字\(0\),
每一秒鐘你會隨機選擇一個\([0,2^n-1]\)的數字,與你手上的數字進行或操作。
選擇數字\(i\)的概率是\(p_i\)。保證\(0\le p_i\le 1,\sum p_i=1\)
問期望多少秒後,你手上的數字變成\(2^n-1\)。
data range
\[n\le 20\]
solution
之前一直在想分治怎麽做
發現根本遞推不了
於是\(gg\)
考慮\(Min-max\)容斥。
我們知道最終答案\(Ans=E(max_{i=1}^{n}f_i)\),其中\(f_i\)表示第\(i\)位變成\(1\)的次數
由\(Min-max\)
\[\max\{S\}=\sum_{T\subseteq S}(-1)^{|T|+1}\times \min\{T\}\]
令\(S=\{f_i\}\)那麽
\[E(\max\{S\})=E(\sum_{T\subseteq S}(-1)^{|T|+1}\times \min\{T\})=\max\{S\}=\sum_{T\subseteq S}(-1)^{|T|+1}\times E(\min\{T\})\]
現在的問題變為如何求\(E(\min\{T\})\)
只要\(T\)中有一位被或上即可,因此
\[E(\min\{T\})=\frac{1}{\sum_{i\cup T\not=\varnothing}p_i}\]
而\(\sum_{i\cup T\not=\varnothing}p_i=1-\sum_{i\subseteq \overline{T}}p_i\)
於是直接\(FWT\)或高維前綴和即可
Code
#include<algorithm> #include<iostream> #include<cstdlib> #include<iomanip> #include<cstring> #include<complex> #include<vector> #include<cstdio> #include<string> #include<bitset> #include<ctime> #include<cmath> #include<queue> #include<stack> #include<map> #include<set> #define Cpy(x,y) memcpy(x,y,sizeof(x)) #define Set(x,y) memset(x,y,sizeof(x)) #define FILE "a" #define mp make_pair #define pb push_back #define RG register #define il inline using namespace std; typedef unsigned long long ull; typedef vector<int>VI; typedef long long ll; typedef double dd; const int N=1<<20; const int M=1e7+10; const int mod=1e9+7; const int base=26; const dd eps=1e-6; const int inf=2147483647; const ll INF=1ll<<60; const ll P=100000; il ll read(){ RG ll data=0,w=1;RG char ch=getchar(); while(ch!=‘-‘&&(ch<‘0‘||ch>‘9‘))ch=getchar(); if(ch==‘-‘)w=-1,ch=getchar(); while(ch<=‘9‘&&ch>=‘0‘)data=data*10+ch-48,ch=getchar(); return data*w; } il void file(){ srand(time(NULL)+rand()); freopen(FILE".in","r",stdin); freopen(FILE".out","w",stdout); } il int count(int x){int r=0;while(x)x&=(x-1),r++;return r;} int n,m;dd p[N],ans; int main() { m=read();n=(1<<m); for(RG int i=0;i<n;i++)scanf("%lf",&p[i]); for(RG int i=1;i<n;i<<=1) for(RG int j=0,l=i<<1;j<n;j+=l) for(RG int k=0;k<i;k++) p[i+j+k]+=p[j+k]; for(RG int i=0;i<n;i++)p[i]=1/(1-p[i]); for(RG int i=0;i<n-1;i++)count(n-i-1)&1?ans+=p[i]:ans-=p[i]; if(ans>INF)return puts("INF"),0;printf("%.10lf\n",ans);return 0; }
[HAOI2015]按位或