[BZOJ 4036][HAOI2015]按位或
阿新 • • 發佈:2019-01-09
4036: [HAOI2015]按位或
Time Limit: 10 Sec Memory Limit: 256 MBSec Special Judge
Submit: 746 Solved: 456
[Submit][Status][Discuss]Description
剛開始你有一個數字0,每一秒鐘你會隨機選擇一個[0,2^n-1]的數字,與你手上的數字進行或(c++,c的|,pascal 的or)操作。選擇數字i的概率是p[i]。保證0<=p[i]<=1,Σp[i]=1問期望多少秒後,你手上的數字變成2^n-1。Input
第一行輸入n表示n個元素,第二行輸入2^n個數,第i個數表示選到i-1的概率
Output
僅輸出一個數表示答案,絕對誤差或相對誤差不超過1e-6即可算通過。如果無解則要輸出INF
Sample Input
2
0.25 0.25 0.25 0.25Sample Output
2.6666666667HINT
對於100%的資料,n<=20
題解
首先無解非常好判. 非 $0$ 概率值全都或起來如果得不到全集就肯定無解了.
這題要求期望...考慮期望等於啥...
每步開始之前, 我們對於非全集的情況都需要繼續進行下一步.
由期望的線性性, 我們可以對於每一步都分開計算.
而進行完一步之後每種狀態的概率要怎麼算呢? 顯然我們有:
$$ c_k=\sum_{i\operatorname{or}j=k} a_it_j$$
顯然這是一個或運算卷積的形式. 所以對於一步的情況, 我們可以FWT解決.
但是在這個題目裡則可能是無限步, 我們繼續來思考.
因為FWT滿足卷積定理, 所以我們有:
$$ \operatorname{FWT}\left(\sum_{i=0}^\infty t^i\right)_k=\sum_{i=0}^\infty \operatorname{FWT}(t)_k^i $$
而等式右邊是個首項為 $1$ 的等比數列求和式, 因為 $\operatorname{FWT}(t)_k\leq 1$ 所以這個值一定收斂於 $\frac 1 {1-\operatorname{FWT}(t)_k}$.
算完 $\operatorname{FWT}^{-1}$ 回去求所有非全集下標的和就行了.
程式碼實現
畢姥爺: 從我們都熟悉的FWT開始
1 #include <bits/stdc++.h> 2 3 const int DWT=1; 4 const int IDWT=-1; 5 const int MAXN=(1<<20)+233; 6 7 double a[MAXN]; 8 9 void FWT(double*,int,int); 10 11 int main(){ 12 int n; 13 scanf("%d",&n); 14 int len=1<<n; 15 int cur=0; 16 for(int i=0;i<len;i++){ 17 scanf("%lf",a+i); 18 if(a[i]>0) 19 cur|=i; 20 } 21 if(cur!=len-1) 22 puts("INF"); 23 else{ 24 FWT(a,len,DWT); 25 for(int i=0;i<len;i++) 26 a[i]=1.0/(1-a[i]); 27 FWT(a,len,IDWT); 28 double ans=0; 29 for(int i=0;i<len-1;i++) 30 ans+=a[i]; 31 printf("%.10f\n",ans); 32 } 33 return 0; 34 } 35 36 void FWT(double* a,int len,int opt){ 37 for(int i=1;i<len;i<<=1) 38 for(int j=0;j<len;j+=i<<1) 39 for(int k=0;k<i;k++) 40 a[j+k+i]+=opt*a[j+k]; 41 }BZOJ 4036