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

    Sol

    题目需要求访问完所有点(假设有 (n) 个)的期望步数,也就是要求

    [E(max{x_1,x_2,cdots,x_n}) ]

    这里 (x_1)(x_2)(cdots)(x_n) 表示第一次到达对应编号的关键点的时间。

    根据 Min-Max 容斥,有

    [E(max{S})=E(max{x_1,x_2,cdots,x_n})=Eleft(sum_{S'subseteq S}(-1)^{|S'|-1}min{S'} ight)=sum_{S'subseteq S}(-1)^{|S'|+1}E(min{S'})(S' ephi) ]

    最后一步等号根据期望的线性性。

    对于某一个集合 (S),设 (f_u) 表示从节点 (u) 开始,第一次到达 任意 给定点期望步数。根据期望 DP:当 (uin S)

    [f_u=0 ]

    (u otin S)

    [f_u=frac1{deg_u}left(f_{fa_u}+sum_{vin son_u}f_v ight)+1 ]

    直接高斯消元复杂度很劣。注意到这是一棵树。

    根据线性代数的知识,使用待定系数法。令 (f_u=k_uf_{fa_u}+b_u),转化下原式

    [egin{aligned} &f_u=frac1{deg_u}left(f_{fa_u}+sum_{vin son_u}k_vf_u+b_v ight)+1\ &Rightarrow deg_uf_u=f_{fa_u}+f_usum_{vin son_u}k_v+sum_{vin son_u}b_v+deg_u\ &Rightarrow f_uleft(deg_u-sum_{vin son_u}k_v ight)=f_{fa_u}+sum_{vin son_u}b_v+deg_u\ &Rightarrow f_u=frac1{deg_u-sum_{vin son_u}k_v}f_{fa_u}+frac{deg_u+sum_{vin son_u}b_v}{deg_u-sum_{vin son_u}k_v} end{aligned} ]

    因此有

    [egin{cases} egin{aligned} k_u&=frac1{deg_u-sum_{vin son_u}k_v}\ b_u&=frac{deg_u+sum_{vin son_u}b_v}{deg_u-sum_{vin son_u}k_v} end{aligned} end{cases} ]

    (u in S) 时,(k_u=b_u=0)

    可以使用 DP 求系数。由于本题的特殊性((n) 很小,或者题目有保证),不存在分母为模数的倍数的情况。故求出系数,复杂度为 (mathcal O(nlog P)),注意要求逆元。总共要求 (2^n) 种情况,故复杂度为 (mathcal O(n2^nlog P))

    预处理所有询问,发现实际上是一个子集枚举,使用 FWT 优化即可。注意系数。这部分复杂度 (mathcal O(n2^n))。总复杂度为 (mathcal O(n2^nlog P))

    Code

    #include <bits/stdc++.h>
    const int N = 19, P = 998244353;
    int n, Q, x;
    struct Edge { int v, nxt; } e[N * 2];
    int G[N], edges = 0;
    void adde(int u, int v) {
    	e[edges++] = (Edge){v, G[u]}; G[u] = edges - 1;
    }
    int inc(int a, int b) { return (a += b) >= P ? a - P : a; }
    int qpow(int a, int b) {
    	int t = 1;
    	for (; b; b >>= 1, a = 1LL * a * a % P)
    		if (b & 1) t = 1LL * t * a % P;
    	return t;
    }
    int k[N], b[N];
    void dfs(int u, int f, int S) {
    	if (S & (1 << u-1)) { k[u] = b[u] = 0; return; }
    	int deg = f ? 1 : 0, K = 0, B = 0;
    	for (int i = G[u], v; ~i; i = e[i].nxt)
    		if (v = e[i].v, v != f)
    			dfs(v, u, S), deg++, K = inc(K, k[v]), B = inc(B, b[v]);
    	k[u] = qpow(inc(deg, P - K), P - 2);
    	b[u] = 1LL * k[u] * (deg + B) % P;
    }
    int a[1 << N];
    void fwt(int *a, int n, int op) {
    	for (int q = 1; q < n; q <<= 1)
    		for (int p = 0; p < n; p += q << 1)
    			for (int i = 0; i < q; i++)
    				a[p+q+i] = inc(a[p+q+i], a[p+i]);
    }
    int main() {
    	scanf("%d%d%d", &n, &Q, &x);
    	memset(G, -1, sizeof G);
    	for (int i = 1; i < n; i++) {
    		int u, v; scanf("%d%d", &u, &v);
    		adde(u, v), adde(v, u);
    	}
    	for (int S = 1; S < 1 << n; S++) {
    		int cnt = 0;
    		dfs(x, 0, S);
    		for (int i = 0; i < n; i++) cnt += (S >> i) & 1;
    		a[S] = cnt & 1 ? b[x] : P - b[x];
    	}
    	fwt(a, 1 << n, 1);
    	while (Q--) {
    		int k, S = 0; scanf("%d", &k);
    		for (int i = 1; i <= k; i++)
    			scanf("%d", &x), S |= 1 << x-1;
    		printf("%d
    ", a[S]);
    	}
    	return 0;
    }
    
  • 相关阅读:
    《DSP using MATLAB》 示例 Example 9.12
    《DSP using MATLAB》示例 Example 9.11
    《DSP using MATLAB》示例 Example 9.10
    《DSP using MATLAB》示例Example 9.9
    《DSP using MATLAB》示例 Example 9.8
    《DSP using MATLAB》示例Example 9.7
    《DSP using MATLAB》示例 Example 9.6
    《DSP using MATLAB》示例Example 9.5
    《DSP using MATLAB》示例 Example 9.4
    (转载)【C++11新特性】 nullptr关键字
  • 原文地址:https://www.cnblogs.com/ac-evil/p/14466726.html
Copyright © 2011-2022 走看看