[BZOJ 4036][HAOI2015]按位或
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 }
本博客已弃用, 新个人主页: https://rvalue.moe, 新博客: https://blog.rvalue.moe