zoukankan      html  css  js  c++  java
  • LG P5643 [PKUWC2018]随机游走

    Description

    给定一棵 $n$个结点的树,你从点 $x$出发,每次等概率随机选择一条与所在点相邻的边走过去。

    有 $q$次询问,每次询问给定一个集合$S$,求如果从 $x$出发一直随机游走,直到点集$S$ 中所有点都至少经过一次的话,期望游走几步。

    特别地,点 $x$(即起点)视为一开始就被经过了一次。

    答案对$998244353$ 取模。

    Solution

    把遍历整个点集的期望时间视为遍历点集中每个点的时间的最大值,就可以使用MinMax容斥

    $$Max(S)=sum_{T subseteq S}(-1)^{|T|-1}Min(T)$$

    令$f(i,S)$表示从$i$到达点集$S$的点的时间最小值,即访问任意一个点的期望时间,所以$Min(S)=f(i,S)$

    其表达式为

    $$f(i,S)=
    egin{cases}
    0& ext{$i in S$}\
    frac{f(fa_i,S)}{deg_i} + frac{sum_{j in son_i}f(j,S)}{deg_i}+1& ext{$i otin S$}\
    end{cases}$$

    设$f(i,S)=A_i imes f(fa_i,S)+B_i$,代入化简得

    $$A_i=frac{1}{deg_i - sum_{j in son_i}A_j},B_i=frac{sum_{jin son_i} B_j + deg_i}{deg_i - sum_{j in son_i}A_j}$$

    预处理子集答案,从下向上递推

    #include<iostream>
    #include<cstdio>
    using namespace std;
    long long n,q,root,tot,head[20],A[20],B[20],deg[20],bits[1100000],ans[1100000];
    const long long mod=998244353;
    struct Edge
    {
        long long to,nxt;
    } edge[40];
    inline long long read()
    {
        long long f=1,w=0;
        char ch=0;
        while(ch<'0'||ch>'9')
        {
            if(ch=='-')
            {
                f=-1;
            }
            ch=getchar();
        }
        while(ch>='0'&&ch<='9')
        {
            w=(w<<1)+(w<<3)+ch-'0';
            ch=getchar();
        }
        return f*w;
    }
    long long ksm(long long a,long long p)
    {
        long long ret=1;
        while(p)
        {
            if(p&1)
            {
                (ret*=a)%=mod;
            }
            (a*=a)%=mod;
            p>>=1;
        }
        return ret;
    }
    void dfs(long long k,long long fa,long long sta)
    {
        if((1<<(k-1))&sta)
        {
            A[k]=B[k]=0;
            return;
        }
        A[k]=B[k]=deg[k];
        for(long long i=head[k]; i; i=edge[i].nxt)
        {
            long long v=edge[i].to;
            if(v!=fa)
            {
                dfs(v,k,sta);
                ((A[k]-=A[v])+=mod)%=mod;
                (B[k]+=B[v])%=mod;
            }
        }
        A[k]=ksm(A[k],mod-2);
        (B[k]*=A[k])%=mod;
    }
    int main()
    {
        n=read();
        q=read();
        root=read();
        for(long long i=1; i<n; i++)
        {
            long long u=read(),v=read();
            edge[++tot]=(Edge){v,head[u]};
            head[u]=tot;
            edge[++tot]=(Edge){u,head[v]};
            head[v]=tot;
            ++deg[u];
            ++deg[v];
        }
        for(long long i=1;i<(1<<n);i++)
        {
            bits[i]+=bits[i>>1]+(i&1);
        }
        for(long long i=1; i<(1<<n); i++)
        {
            dfs(root,0,i);
            if(bits[i]&1)
            {
                ans[i]=B[root];
            }
            else
            {
                ans[i]=mod-B[root];
            }
        }
        for(long long i=0;i<n;i++)
        {
            for(long long j=0;j<(1<<n);j++)
            {
                if((1<<i)&j)
                {
                    (ans[j]+=ans[j^(1<<i)])%=mod;
                }
            }
        }
        for(long long i=1;i<=q;i++)
        {
            long long k=read(),nowsta=0;
            for(long long j=1;j<=k;j++)
            {
                long long num=read();
                nowsta|=(1<<(num-1));
            }
            printf("%lld
    ",ans[nowsta]);
        }
        return 0;
    }
    随机游走
  • 相关阅读:
    Windows 8.1 应用开发 – 触控操作
    Windows Phone App Studio 无码开发手机应用
    尝试HTML + JavaScript 编写Windows App
    Ubuntu远程连接MySQL(connection refused)解决方法
    [MySQL]查看用户权限与GRANT用法
    mysql 创建用户命令-grant
    搭建memcached使用:/usr/bin/phpize 安装memcached扩展的时候报错
    在linux中使用phpize安装php扩展模块
    跟锦数学全部资料
    33套2020数分高代试题参考解答[2020/04/14更新,更多请关注跟锦数学微信公众号]
  • 原文地址:https://www.cnblogs.com/JDFZ-ZZ/p/13445244.html
Copyright © 2011-2022 走看看