zoukankan      html  css  js  c++  java
  • 【题解】Heaps of Fun (概率论)

    【题解】Heaps of Fun (概率论)

    看完题解才发现讲题的时候讲的是什么屎,你说的分段是指分两段吗.......

    简要题意:

    给定你一棵树(不一定是二叉树),每个点有个随机点权,在([0,a[u]])均匀分布,问你这棵树满足堆性质(小根堆)的概率是多少?

    取值如果是整数可以直接DP,但是如果是实数怎么办?

    每个节点搞一个随机变量(X_u),满足(P(X_u=x))表示这个节点是(x)的时候的满足条件的概率,概率分布函数和概率密度函数分别记为(F_u(x),f_u(x)),定义查百度,特别提醒(F_u(x)=sum_{tle x} P(X_u=t))是前缀,而(int f(x)mathrm dx=F(x)+0)

    边界条件很好办,不论咋样都是合法的,但是怎么转移呢??

    假若(X_u=x),那么如果要合法,就要保证(X_{son[u]}< x),而这个概率就是(F_{son[u]}(x))(因为概率分布函数是连续的),所以

    [P(X_u=x)={1over a[u]}prod_{vin son[u]} P(X_v>x) ]

    但是(X)是连续的随机变量,我们只能通过(F,f)来转移。设(low[x])表示(x)子树内最小的(a[u])值,那么这个值是最小满足条件(合法且在定义域内)的值(实际上取不到,只能无限接近),所以(P(X_x>t)=F(low[x])-F(t))。设(=h_u(x))

    根据一些前置姿势(概率论与数理统计上有),(f_x(t)=P(X_x=t)),根据书上的关系就有(F(x)=int f(x)),那么直接积分一下就好了

    答案是(h_{rt}(+inf)=F_{rt}[0])

    //@winlere
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    
    using namespace std;  typedef long long ll; 
    inline int qr(){
    	int ret=0,f=0,c=getchar();
    	while(!isdigit(c))f|=c==45,c=getchar();
    	while(isdigit(c)) ret=ret*10+c-48,c=getchar();
    	return f?-ret:ret;
    }
    typedef vector<int> poly;
    const int mod=1e9+7;
    const int maxn=3e2+5;
    poly f[maxn],e[maxn];
    int low[maxn],a[maxn],n,rt;
    int MOD(const int&x){return x>=mod?x-mod:x;}
    int MOD(const int&x,const int&y){return 1ll*x*y%mod;}
    poly operator * (poly a,poly b){
    	if(a.empty()||b.empty()) return poly();
    	poly ret(a.size()+b.size()-1,0);
    	for(int t=0,ed=a.size();t<ed;++t)
    		for(int i=0,ed=b.size();i<ed;++i)
    			ret[t+i]=MOD(ret[t+i]+MOD(a[t],b[i]));
    	return ret;
    }
    int ksm(const int&ba,const int&p){
    	int ret=1;
    	for(int t=p,b=ba;t;t>>=1,b=1ll*b*b%mod)
    		if(t&1) ret=1ll*ret*b%mod;
    	return ret;
    }
    void Int(poly&x){
    	if(x.empty()) return;
    	x.resize(x.size()+1);
    	for(int t=x.size()-1;t;--t)
    		x[t]=MOD(x[t-1],ksm(t,mod-2));
    	x[0]=0;
    }
    int F(const poly&x,int g){
    	int ret=0;
    	for(int t=x.size()-1;~t;--t)
    		ret=MOD(MOD(ret,g)+x[t]);
    	return ret;	
    }
    void add(int fr,int to){e[fr].push_back(to);}
    void dfs(int now){
    	low[now]=a[now]; f[now].resize(1,1);
    	for(auto t:e[now])
    		dfs(t),low[now]=min(low[now],low[t]),f[now]=f[now]*f[t];
    	f[now]=f[now]*(poly){ksm(a[now],mod-2)};
    	Int(f[now]); f[now][0]=F(f[now],low[now]);
    	for(int t=1,ed=f[now].size();t<ed;++t) f[now][t]=MOD(mod-f[now][t]);
    }
    
    int main(){
    	n=qr();
    	for(int t=1;t<=n;++t){
    		a[t]=qr();
    		int fa=qr();
    		if(fa) add(fa,t);
    		else rt=t;
    	}
    	dfs(rt);
    	printf("%d
    ",f[rt][0]);
    	return 0;
    }
    
    
    
  • 相关阅读:
    API函数
    平台调用教程
    查看网页源文件方法
    网页端商品链接转换为手机端链接的部分网址规则
    中文分词消除歧义简单思想
    java 链接数据库时的配置代码
    手机参数更新语句根据Id 可以得到某手机的各种参数
    中文分词—基于Lucene的分词器—支持中英文混合词
    修改Imdict做自己的分词器
    制作可输入的下拉框
  • 原文地址:https://www.cnblogs.com/winlere/p/12705668.html
Copyright © 2011-2022 走看看