[PKUWC2018]随机游走

题目大意

给你一颗树和根,每次询问从根出发,随机走到有连边的结点,经过集合S中所有结点的步数期望

\(1 \leq n \leq 18,1 \leq Q \leq 5000\)

解题思路

首先我们要求出所有集合\(S\)经过至少一个\(S\)中的点的步数期望(为最值反演铺垫)

令\(dp_{S,i}\)表示以i为起点,要经过集合S中至少一个点的步数期望

那么\(dp_{S,i}=\frac{1}{dig_i}(dp_{S,fa_i}+1+\sum_{v\in son}{dp_{S,v}+1})\),\(dig\)表示\(i\)的度数

根据套路,我们假设\(dp_{S,i}=A_idp_{S,fa_i}+B_i\)

\[
\begin{align}
dp_{S,i} & =\frac{1}{dig_i}(dp_{S,fa_i}+1+\sum_{v\in son}{dp_{S,v}+1}) \ & =\frac{1}{dig_i}(dp_{S,fa_i}+1+\sum_{v\in son}{A_vdp_{S,i}+B_v+1}) \ & =\frac{1}{dig_i}(dp_{S,fa_i}+dp_{S,i}\sum_{v\in son}{A_v}+\sum_{v\in son}{B_v})+1 \ & =\frac{1}{dig_i}(dp_{S,fa_i}+dp_{S,i}sigA+sigB)+1 \ dig_idp_{S,i} & =dp_{S,fa_i}+dp_{S,i}sigA+sigB+1 \ (dig_i-sigA)dp_{S,i} & =dp_{S,fa_i}+sigB+1 \ dp_{S,i} & =\frac{1}{dig_i-sigA}dp_{S,fa_i}+\frac{sigB+1}{dig_i-sigA} \ \end{align}
\]

于是我们得到了

\[ A_i=\frac{1}{dig_i-sigA} \]

\[ B_i=\frac{sigB+1}{dig_i-sigA} \]

显然如果\(i\in S\)那么\(A_i=B_i=0\)

然后A,B是可以在树上dp的(因为式子只和它的孩子有关)

那么我们要求的

\[
\begin{align}
dp_{S,root} & = A_{root}dp_{S,fa_{root}}+B_{root} \ & = B_{root} \ \end{align}
\]

于是每次询问集合S,只需要进行最值反演,\(max(S)=\sum_{S‘\subseteq S}{dp_{S‘,root}\cdot (-1)^{|S‘|+1}}\)

\(max(S)\)即为每次询问的答案

#include<iostream>
#include<cstdio>

const int P=998244353;

struct edge{
    int to,next;
}E[60];
int H[30],tot;
void add_edge(int a,int b){
    E[++tot]=(edge){b,H[a]};H[a]=tot;
    E[++tot]=(edge){a,H[b]};H[b]=tot;
}

int n,Q,St,x,y,k,ch[30];
long long ans;
long long A[30],B[30],dp[3000000],dig[30];

long long inv(long long k){return (k==1)?(1):((P-P/k)*inv(P%k)%P);}

void dfs(int S,int now,int fa){
    if ((1<<(now-1))&S){
        A[now]=B[now]=0;
        return;
    }
    long long sigA=0,sigB=0;
    for (int i=H[now];i;i=E[i].next){
        if (E[i].to==fa) continue;
        dfs(S,E[i].to,now);
        sigA=(sigA+A[E[i].to])%P;
        sigB=(sigB+B[E[i].to])%P;
    }
    long long Inv=(dig[now]==sigA)?(0):(inv(dig[now]-sigA));
    A[now]=Inv;
    B[now]=(sigB+dig[now])%P*Inv%P;
}

void Min_Max(int now,int S,int f){
    if (now>k){ans=(ans+f*dp[S]%P+P)%P;return;}
    Min_Max(now+1,S,f);
    Min_Max(now+1,S|(1<<(ch[now]-1)),-f);
}

int main(){
    scanf("%d%d%d",&n,&Q,&St);
    for (int i=1;i<n;i++){
        scanf("%d%d",&x,&y);
        dig[x]++;dig[y]++;
        add_edge(x,y);
    }
    for (int i=0;i<(1<<n);i++){
        dfs(i,St,0);
        dp[i]=B[St];
    }
    for (int i=1;i<=Q;i++){
        scanf("%d",&k);
        for (int j=1;j<=k;j++) scanf("%d",&ch[j]);
        ans=0;
        Min_Max(1,0,-1);
        printf("%lld\n",ans);
    }
}

原文地址:https://www.cnblogs.com/ytxytx/p/9580073.html

时间: 2024-08-18 18:10:44

[PKUWC2018]随机游走的相关文章

Loj #2542. 「PKUWC2018」随机游走

Loj #2542. 「PKUWC2018」随机游走 题目描述 给定一棵 \(n\) 个结点的树,你从点 \(x\) 出发,每次等概率随机选择一条与所在点相邻的边走过去. 有 \(Q\) 次询问,每次询问给定一个集合 \(S\),求如果从 \(x\) 出发一直随机游走,直到点集 \(S\) 中所有点都至少经过一次的话,期望游走几步. 特别地,点 \(x\)(即起点)视为一开始就被经过了一次. 答案对 $998244353 $ 取模. 输入格式 第一行三个正整数 \(n,Q,x\). 接下来 \(

随机游走

在python中,可以利用数组操作来模拟随机游走. 下面是一个单一的200步随机游走的例子,从0开始,步长为1和-1,且以相等的概率出现.纯Python方式实现,使用了内建的 random 模块: # 随机游走 import matplotlib.pyplot as plt import random position = 0 walk = [position] steps = 200 for i in range(steps): step = 1 if random.randint(0, 1)

随机游走的matlab实现

<span style="font-family:KaiTi_GB2312;font-size:14px;">%随机游走产生图像效果实现,随机游走类似布朗运动,就是随机的向各个方向走</span> <span style="font-family:KaiTi_GB2312;font-size:14px;"><span style="color: rgb(68, 68, 68); line-height: 21px;

bzoj 3143 随机游走

题意: 给一个简单无向图,一个人从1号节点开始随机游走(即以相同概率走向与它相邻的点),走到n便停止,问每条边期望走的步数. 首先求出每个点期望走到的次数,每条边自然是从它的两个端点走来. 1 /************************************************************** 2 Problem: 3143 3 User: idy002 4 Language: C++ 5 Result: Accepted 6 Time:736 ms 7 Memory:

[PKUWC 2018]随机游走

Description 题库链接 给定一棵 \(n\) 个结点的树,你从点 \(x\) 出发,每次等概率随机选择一条与所在点相邻的边走过去. 有 \(Q\) 次询问,每次询问给定一个集合 \(S\) ,求如果从 \(x\) 出发一直随机游走,直到点集 \(S\) 中所有点都至少经过一次的话,期望游走几步. 特别地,点 \(x\)(即起点)视为一开始就被经过了一次. 答案对 \(998244353\) 取模. Solution 不妨设 \(f_{i,S}\) 表示在点 \(i\) 时,要遍历集合

随机游走模型(RandomWalk Mobility)

随机游走模型由首先由爱因斯坦在1926年以数学方式描述.由于自然界中的许多实体会以不可预知的方式移动,因此随机游走模型用来描述这种不稳定的移动.在这种移动模型中,移动节点随机选择一个方向和速度来从当前位置移动到新的位置.新的速度和方向分别从预定义的范围[speedmin,speedmax]和[0,2].移动节点的每次移动会以恒定的时间间隔t或恒定的行进距离d进行,结束后会计算新的方向和速度.如果此模型的移动节点到达模拟边界,则它将从模拟边界"弹回",其角度有入射方向确定,然后沿着这条路

带黑洞的随机游走问题

对于无黑洞的随机游走问题可以使用线性方程组求解,对于有黑洞的随机游走问题就无法使用线性方程组进行求解了. 有黑洞的随机游走问题举例: 随机给定一个魔方状态,随机旋转期望通过多少步才能旋转到目标状态? 醉汉回家问题:一个人在x点处喝醉了,在N维空间中游走,它回到出发点的概率是多少?求p(N) zhihu 一个整型数字x=6000,每次增长101的概率为49.32%,每次减少100元的概率为50.68%,问最终x&tt;7000的概率是多少? 显然,这个问题相当于一个随机游走问题,一共有100~70

「Luogu4321」随机游走

「Luogu4321」随机游走 题目描述 有一张 \(n\) 个点 \(m\) 条边的无向图,\(Q\) 组询问,每次询问给出一个出发点和一个点集 \(S\) ,求从出发点出发随机游走走遍这个点集的期望步数. \(1 \leq n \leq 18, 1 \leq Q \leq 10^5\) 解题思路 : 听说是 \(\text{pkuwc2018d2t3}\) 加强版?但是原题时限是1s,各种卡不进去感觉一定要写 \(\text{Min-Max}\) 容斥,不过反正我今年听指导建议没报 \(\t

「PKUWC2018」随机游走

题面在这里! 显然你如果直接带一个子集到树上dp的话复杂度是会炸上天的23333. 考虑期望也是可以进行min_max容斥的,也就是: max{S} = ∑ min{T} * (-1) ^( |T|+1 ) ,其中T是S的一个非空子集,max{S}和min{S}分别代表集合中所有条件都被满足的期望时间 和 集合中至少有一个条件被满足的期望时间, 当然对本题来说就是 所有钦定的点都被到过一次的期望时间 和 第一次到某个钦定的点的期望时间.... 发现min非常的好算,对于每个集合直接一次树上dp