Kattis heapsoffun Heaps of Fun

Link
\(f_u(x)\)表示\(u\)节点取值为\(x\)且该节点子树满足性质的概率,显然这是一个连续分布的概率密度函数。
\(F_u(x)=\int_0^xf_u(x)\)即概率分布函数,\(G_u(x)=\int_x^{b_u}f_u(x)=F_u(b_u)-F_u(x)\)
我们默认\(f_u(x),F_u(x),G_u(x)\)的定义域为\([0,b_u]\),最后的答案就是\(G_{root}(0)\)
对于叶子节点\(u\)而言,\(f_u(x)=\frac1{b_u}\)
对于非叶子节点\(u\)而言,\(f_u(x)=\frac1{b_u}\prod\limits_{v\in son_u}G_v(x)\)
不难发现\(f_u(x),F_u(x),G_u(x)\)都是多项式。
暴力多项式乘法完成即可,时间复杂度为\(O(n^3)\)

#include<cstdio>
#include<vector>
#include<cstring>
const int N=307,P=1000000007;
int n,a[N],inv[N];std::vector<int>e[N];
struct poly{int a[N],deg;poly(){memset(a,0,sizeof a),deg=0;}poly(int x){memset(a,0,sizeof a),a[0]=x,deg=1;}int&operator[](int x){return a[x];}};
struct node{poly a;int r;};
int read(){int x;scanf("%d",&x);return x;}
void inc(int&a,int b){a+=b-P,a+=a>>31&P;}
int sub(int a,int b){return a-=b,a+(a>>31&P);}
int mul(int a,int b){return 1ll*a*b%P;}
int pow(int a,int k){int r=1;for(;k;k>>=1,a=mul(a,a))if(k&1)r=mul(a,r);return r;}
poly sub(poly f,poly g)
{
    poly h;h.deg=std::max(f.deg,g.deg);
    for(int i=0;i<h.deg;++i) h[i]=sub(f[i],g[i]);
    return h;
}
poly Int(poly f)
{
    poly g;g.deg=f.deg+1;
    for(int i=0;i<f.deg;++i) g[i+1]=mul(f[i],inv[i+1]);
    return g;
}
poly mul(poly f,poly g)
{
    poly h;h.deg=f.deg+g.deg-1;
    for(int i=0;i<f.deg;++i) for(int j=0;j<g.deg;++j) inc(h[i+j],mul(f[i],g[j]));
    return h;
}
int cal(poly f,int x)
{
    int s=0;
    for(int i=0,t=1;i<f.deg;++i,t=mul(t,x)) inc(s,mul(t,f[i]));
    return s;
}
node merge(node a,node b){return {mul(a.a,b.a),std::min(a.r,b.r)};}
node dfs(int u,int fa)
{
    node ans={poly(pow(a[u],P-2)),a[u]};poly t;
    for(int v:e[u]) if(v^fa) ans=merge(ans,dfs(v,u));
    return t=Int(ans.a),node{sub(cal(t,ans.r),t),ans.r};
}
int main()
{
    n=read(),inv[0]=inv[1]=1;
    for(int i=2;i<=300;++i) inv[i]=mul(P-P/i,inv[P%i]);
    for(int i=1;i<=n;++i) a[i]=read(),e[read()].push_back(i);
    printf("%d",dfs(e[0][0],0).a[0]);
}
posted @ 2020-04-07 22:03  Shiina_Mashiro  阅读(216)  评论(0编辑  收藏  举报