题解-概率计算器
Problem
求给定式子的期望:题面
Solution
由于式子是由\(\max ,\min\)组成的,而这东西是基于比较大小的,所以我们需要想想在基于比较的情况下方便实现的东西
设\(f(x)\)表示式子小于等于\(x\)的概率,\(g(x)\)表示式子大于等于\(x\)的概率
则对于单个变量,易证有:
\(f(x)=x\\g(x)=1-f(x)\)
对于式子\(\max(x_1,x_2)\)
\[f(x)=f_1(x)\cdot f_2(x)
\]
\[g(x)=1-f_1(x)\cdot f_2(x)
\]
对于式子\(\min(x_1,x_2)\)
\[g(x)=g_1(x)\cdot g_2(x)
\]
\[f(x)=1-g_1(x)\cdot g_2(x)
\]
接下来考虑如何统计答案
众所周知,答案可以表达为
\[\int_0^1p(ans=x)\cdot x\cdot dx
\]
由于\(f(x)\)表示的是式子小于等于\(x\)的概率
即\(f(x)=p(ans\leq x)\),则有\(f'(x)=p(ans=x)\)
即最终答案为
\[\int_0^1f'(x)\cdot x\cdot dx
\]
\(f(x)\)可以由递归求解
至于原式的话,只要简单求导积分即可
注意:如果在oj上下了数据,并且在第六位小数处出现1的误差,是因为oj上下载数据的链接有问题?提交即可AC
Code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define rg register
template <typename _Tp> inline _Tp read(_Tp&x){
char c11=getchar(),ob=0;x=0;
while(c11^'-'&&!isdigit(c11))c11=getchar();if(c11=='-')ob=1,c11=getchar();
while(isdigit(c11))x=x*10+c11-'0',c11=getchar();if(ob)x=-x;return x;
}
const int N=100;
int l[N],r[N],m[N];
int ps[10101],st[N];
char s[10101];
int n,len;
struct poly{
ll a[N];int d;
inline poly(){memset(a,0,sizeof(a)),d=0;}
friend inline poly operator * (poly A,poly B){
poly res;res.d=A.d+B.d-1;
for(rg int i=0;i<A.d;++i)
for(rg int j=0;j<B.d;++j)
res.a[i+j]+=A.a[i]*B.a[j];
return res;
}
friend inline poly operator - (poly A,poly B){
poly res;res.d=max(A.d,B.d);
for(rg int i=0;i<res.d;++i)
res.a[i]=A.a[i]-B.a[i];
return res;
}
inline void deri(){
for(rg int i=0;i<d-1;++i)
a[i]=a[i+1]*(i+1);
a[--d]=0;
}
}ans,vec;
poly calc(int opt,int L,int R){
if(s[L+1]=='x'){
poly res;res.d=2;
if(!opt)res.a[1]=1;
else res.a[1]=-1,res.a[0]=1;
return res;
}
for(int i=L+1;i<=R;++i)if(ps[i]){
int id=ps[i];
if(!opt)
if(s[i-1]=='x')return calc(opt,l[id],m[id])*calc(opt,m[id]+1,r[id]);
else return vec-(calc(opt^1,l[id],m[id])*calc(opt^1,m[id]+1,r[id]));
else
if(s[i-1]=='n')return calc(opt,l[id],m[id])*calc(opt,m[id]+1,r[id]);
else return vec-(calc(opt^1,l[id],m[id])*calc(opt^1,m[id]+1,r[id]));
}
}
void init();
int main(){
vec.d=2;vec.a[0]=1;
while(~scanf("%s",s)){
init();
ans=calc(0,-1,len-1);
ans.deri();
for(rg int i=ans.d;i;--i)
ans.a[i]=ans.a[i-1];
ans.a[0]=0;++ans.d;
double res=0;
for(rg int i=ans.d;i;--i)
res+=1.0*(ans.a[i-1]%i)/i;
while(res<=0)++res;while(res>=1)--res;
printf("%.6lf\n",res);
}return 0;
}
void init(){
scanf("%s",s);getchar();
cin.getline(s,10000);
len=strlen(s);
memset(ps,0,sizeof(ps));
int idc=0,tp=0;
for(int i=0;i<len;++i){
if(s[i]=='(')ps[l[st[++tp]=++idc]=i]=idc;
else if(s[i]==',')m[st[tp]]=i;
else if(s[i]==')')r[st[tp--]]=i;
}
}