博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
LOJ#2542 随机游走
阅读量:6241 次
发布时间:2019-06-22

本文共 3008 字,大约阅读时间需要 10 分钟。

解:首先minmax容斥变成经过集合t的第一个点就停止的期望步数。对于某个t,设从x开始的期望步数为f(x)

如果x∈t,f(x) = 0。否则f(x) = ∑f(y) / in[x] + 1

树上高斯消元。从叶子往上,可以发现每个点都可以表示为Af(fa) + B

于是我们推一波式子,,就可以对每个t,O(n)求出f(root)。

然后每个询问就枚举子集。

注意DFS的时候可以剪枝,遇到x∈t就返回,否则T飞.....

 

1 #include 
2 3 const int N = 30, MO = 998244353; 4 5 inline void read(int &x) { 6 x = 0; 7 char c = getchar(); 8 while(c < '0' || c > '9') c = getchar(); 9 while(c >= '0' && c <= '9') { 10 x = x * 10 + c - 48; 11 c = getchar(); 12 } 13 return; 14 } 15 16 struct Edge { 17 int nex, v; 18 }edge[N << 1]; int tp; 19 20 int n, rt, e[N], A[N], B[N], now, in[N], ans[1 << 19], cnt[1 << 19], ans2[1 << 19]; 21 22 inline int qpow(int a, int b) { 23 int ans = 1; 24 a = (a + MO) % MO; 25 while(b) { 26 if(b & 1) ans = 1ll * ans * a % MO; 27 a = 1ll * a * a % MO; 28 b = b >> 1; 29 } 30 return ans; 31 } 32 33 inline void add(int x, int y) { 34 tp++; 35 edge[tp].v = y; 36 edge[tp].nex = e[x]; 37 e[x] = tp; 38 return; 39 } 40 41 void DFS(int x, int f) { 42 if(((1 << (x - 1)) | now) == now) { 43 A[x] = B[x] = 0; 44 return; 45 } 46 int sa = 0, sb = 0; 47 for(int i = e[x]; i; i = edge[i].nex) { 48 int y = edge[i].v; 49 if(y == f) continue; 50 DFS(y, x); 51 sa = (sa + A[y]) % MO; 52 sb = (sb + B[y]) % MO; 53 } 54 55 A[x] = qpow(in[x] - sa, MO - 2); 56 B[x] = 1ll * A[x] * (in[x] + sb) % MO; 57 58 return; 59 } 60 61 int main() { 62 int q; 63 read(n); read(q); read(rt); 64 for(register int i = 1, x, y; i < n; i++) { 65 read(x); read(y); 66 add(x, y); add(y, x); 67 in[x]++; in[y]++; 68 } 69 70 int lm = 1 << n; 71 /*for(now = 1; now < lm; now++) { 72 //memset(A, ) 73 DFS(rt, 0); 74 ans[now] = B[rt]; 75 }*/ 76 memset(ans, -1, sizeof(ans)); 77 memset(ans2, -1, sizeof(ans2)); 78 79 for(register int i = 1; i < lm; i++) { 80 cnt[i] = 1 + cnt[i - (i & (-i))]; 81 } 82 83 /// prework OVER 84 for(register int i = 1, k; i <= q; i++) { 85 read(k); 86 int s = 0; 87 for(register int j = 1, x; j <= k; j++) { 88 read(x); 89 s |= (1 << (x - 1)); 90 } 91 int Ans = 0; 92 if(ans2[s] != -1) { 93 Ans = ans2[s]; 94 } 95 else { 96 for(register int t = s; t; t = (t - 1) & s) { 97 if(ans[t] == -1) { 98 now = t; 99 DFS(rt, 0);100 ans[t] = B[rt];101 }102 if(cnt[t] & 1) Ans = (Ans + ans[t]) % MO;103 else Ans = (Ans - ans[t] + MO) % MO;104 }105 ans2[s] = Ans;106 }107 printf("%d\n", (Ans + MO) % MO);108 }109 110 return 0;111 }
AC代码

 

转载于:https://www.cnblogs.com/huyufeifei/p/10518598.html

你可能感兴趣的文章
常用正则表达式
查看>>
超大批量删除redis中无用key+配置
查看>>
guid正则表达
查看>>
Javascript的this用法
查看>>
PHP的学习--新特性
查看>>
Linux下安装配置Nexus
查看>>
JDBC插入数据超长时无法自动截断问题
查看>>
Tyrion中文文档(含示例源码)
查看>>
MySQL 面试基础
查看>>
利用GPU实现翻页效果
查看>>
C# 中的await
查看>>
java以流的形式输出文件
查看>>
『PyTorch』第十三弹_torch.nn.init参数初始化
查看>>
linux 查找目录下的文件内容并替换(批量)
查看>>
iphone遮住听筒/感应器/摄像头黑屏的解决办法
查看>>
python 抓取alexa数据
查看>>
UART、SPI和I2C详解
查看>>
兼容N多浏览器的CSS阴影效果
查看>>
Multiple arguments in Django template filters
查看>>
ARM11-Linux2.6-Button-Driver-Base-info
查看>>