首先考虑
m
i
n
−
m
a
x
min-max
min−max 容斥
可得
E
(
S
)
=
∑
T
⊆
S
(
−
1
)
∣
T
∣
−
1
f
(
T
)
E(S)=\sum\limits_{T\subseteq S}(-1)^{|T|-1}f(T)
E(S)=T⊆S∑(−1)∣T∣−1f(T)
其中
f
(
T
)
f(T)
f(T) 为从
x
x
x 第一次到达
T
T
T 集合中任意一点的期望步数
树上随机游走可以想到树上高斯消元,所以开始推式子
记
g
(
i
,
S
)
g(i,S)
g(i,S) 为从
i
i
i 第一次到达
S
S
S 集合中任意一点的期望步数(后面省略
S
S
S)
g
(
i
)
=
1
+
1
d
e
g
i
f
f
a
+
1
d
e
g
i
×
∑
v
∈
s
o
n
(
i
)
f
v
=
1
+
1
d
e
g
i
f
f
a
+
1
d
e
g
i
×
∑
v
∈
s
o
n
(
i
)
(
A
v
f
i
+
B
v
)
=
1
+
1
d
e
g
i
f
f
a
+
(
1
d
e
g
i
×
∑
v
∈
s
o
n
(
i
)
A
v
)
f
i
+
1
d
e
g
i
×
∑
v
∈
s
o
n
(
i
)
B
v
g(i)=1+\frac{1}{deg_i}f_{fa}+\frac{1}{deg_i}\times\sum\limits_{v\in son(i)}f_v\\ =1+\frac{1}{deg_i}f_{fa}+\frac{1}{deg_i}\times\sum\limits_{v\in son(i)}(A_vf_i+B_v)\\ =1+\frac{1}{deg_i}f_{fa}+(\frac{1}{deg_i}\times\sum\limits_{v\in son(i)}A_v)f_i+\frac{1}{deg_i}\times\sum\limits_{v\in son(i)}B_v
g(i)=1+degi1ffa+degi1×v∈son(i)∑fv=1+degi1ffa+degi1×v∈son(i)∑(Avfi+Bv)=1+degi1ffa+(degi1×v∈son(i)∑Av)fi+degi1×v∈son(i)∑Bv
所以
(
1
−
1
d
e
g
i
×
∑
v
∈
s
o
n
(
i
)
A
v
)
f
i
=
1
d
e
g
i
f
f
a
+
1
+
1
d
e
g
i
×
∑
v
∈
s
o
n
(
i
)
B
v
(1-\frac{1}{deg_i}\times\sum\limits_{v\in son(i)}A_v)f_i=\frac{1}{deg_i}f_{fa}+1+\frac{1}{deg_i}\times\sum\limits_{v\in son(i)}B_v
(1−degi1×v∈son(i)∑Av)fi=degi1ffa+1+degi1×v∈son(i)∑Bv
把
f
i
f_i
fi 的系数除过去即可得到
A
i
,
B
i
A_i,B_i
Ai,Bi,式子过于复杂,写了可能也看不清
我们可以钦定
x
x
x 为根,那么
f
(
S
)
=
B
x
f(S)=B_x
f(S)=Bx
计算
f
f
f 的时间复杂度为
O
(
n
2
n
)
O(n2^n)
O(n2n)
然后我们发现
m
i
n
−
m
a
x
min-max
min−max 容斥的式子是一个子集卷积,直接
f
w
t
fwt
fwt 即可,时间复杂度
O
(
n
2
n
)
O(n2^n)
O(n2n)
其实不用
f
w
t
fwt
fwt 也可以过题,时间复杂度为
O
(
q
2
n
)
O(q2^n)
O(q2n),但常数很小
#include
using namespace std;
const int N=20,P=998244353;
int n,q,rt,f[1<<18],cnt[1<<18],A[N],B[N];
int e[N<<1],ne[N<<1],h[N],idx;
inline int read(){
int FF=0,RR=1;
char ch=getchar();
for(;!isdigit(ch);ch=getchar()) if(ch=='-') RR=-1;
for(;isdigit(ch);ch=getchar()) FF=(FF<<1)+(FF<<3)+ch-48;
return FF*RR;
}
inline void inc(int &x,int y){
x+=y;
if(x>=P) x-=P;
}
int qmi(int a,int b){
int res=1;
for(;b;b>>=1){
if(b&1) res=1ll*res*a%P;
a=1ll*a*a%P;
}
return res;
}
void dfs(int u,int fa,int S){
if(S>>u&1) return;
int rs1=0,rs2=0,deg=(fa>=0);
for(int i=h[u];~i;i=ne[i]){
int v=e[i];if(v==fa) continue;
dfs(v,u,S);deg++;
inc(rs1,A[v]),inc(rs2,B[v]);
}
int ivdeg=qmi(deg,P-2);
rs1=(P+1-1ll*rs1*ivdeg%P)%P,rs1=qmi(rs1,P-2);
rs2=1ll*rs2*ivdeg%P+1;
A[u]=1ll*ivdeg*rs1%P,B[u]=1ll*rs2*rs1%P;
}
void add(int x,int y){ e[idx]=y,ne[idx]=h[x],h[x]=idx++;}
void fwt(){
n=1<<n;
for(int mid=1;mid<n;mid<<=1)
for(int i=0;i<n;i+=mid<<1)
for(int j=0;j<mid;j++){
f[i+j+mid]+=f[i+j];
if(f[i+j+mid]>=P) f[i+j+mid]-=P;
}
}
int main(){
n=read(),q=read(),rt=read();rt--;
memset(h,-1,sizeof(h));
for(int i=1;i<n;i++){
int x=read(),y=read();x--,y--;
add(x,y),add(y,x);
}
for(int S=0;S<1<<n;S++){
for(int i=0;i<n;i++) A[i]=0,B[i]=0;
dfs(rt,-1,S),f[S]=B[rt];
cnt[S]=__builtin_popcount(S)+1;
if(cnt[S]&1) f[S]=P-f[S];
}
fwt();
while(q--){
int k=read(),State=0;
while(k--){ int x=read();State|=1<<(x-1);}
printf("%d\n",f[State]);
}
fprintf(stderr,"%d ms\n",int(1e3*clock()/CLOCKS_PER_SEC));
return 0;
}
/*
f[i][S]:从i出发,第一个到点集S中的点的期望步数
*/