The Preliminary Contest for ICPC Asia Xuzhou 2019: J. Random Access Iterator(概率dp):

其实这题也是比较简单的,只不过我们队开这题的时候已经快结束了,导致满脑子混沌。。。
以至于我样例手动模拟都算错了概率。。。。。
题目连接:点击这里

dp[u] 表示 u这个点向下能到达最深深度的概率,因为对于每个点要找k次,只要其中有一次能到达最深即可。但是对于不能到达要所有次都不能到达,比较好求,那么我们就可以求 u这个点向下不能到达最深深度的概率p,用1减去p就是dp[u]。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<set>
#include<deque>
#include<map>
#include<vector>
#include<cmath>
#define ll long long
#define llu unsigned ll
using namespace std;
const double eps = 1e-8;
const ll lnf=0x3f3f3f3f3f3f3f3f;
const int inf = 0x3f3f3f3f;
const int maxn=2000010;
const int mod=1e9+7;
int head[maxn],ver[maxn],nt[maxn];
int d[maxn],si[maxn],ans=0,tot=1;
ll dp[maxn];

void add(int x,int y)
{
    ver[++tot]=y,nt[tot]=head[x],head[x]=tot;
}

ll mypow(ll a,ll b)
{
    ll ans=1;
    while(b)
    {
        if(b&1) ans=ans*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return ans;
}

void dfs1(int x,int fa)
{
    for(int i=head[x];i;i=nt[i])
    {
        int y=ver[i];
        if(y==fa) continue;
        si[x]++;
        d[y]=d[x]+1;
        dfs1(y,x);
        ans=max(ans,d[y]);
    }
}

void dfs2(int x,int fa)
{
    if(d[x]==ans)
    {
        dp[x]=1;
        return ;
    }

    ll inv=mypow(si[x],mod-2);
    ll cnt=0;
    for(int i=head[x];i;i=nt[i])
    {
        int y=ver[i];
        if(y==fa) continue;
        dfs2(y,x);
        cnt=(cnt+(1-dp[y]+mod)*inv%mod)%mod;
    }
    dp[x]=(1-mypow(cnt,si[x])+mod)%mod;
}

int main(void)
{
    int n,x,y;

    scanf("%d",&n);
    for(int i=1;i<n;i++)
    {
        scanf("%d%d",&x,&y);
        add(x,y);
        add(y,x);
    }
    dfs1(1,0);
    dfs2(1,0);
    printf("%lld\n",dp[1]);
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值