Upd 2021.10.21 更改了状态定义。

记 \(S(u)\) 表示 \(u\) 结点的相邻结点的集合。

又记 \(p(u)\) 表示走到了 \(u\) 且下一步继续留在 \(u\) 结点的概率,那么下一步离开 \(u\) 结点的概率即为 \(1 - p(u)\)。

设 \(f(i, j)\) 表示 Petya 在 \(i\) 且 Vasya 在 \(j\) 这种状态的期望出现次数。

可知所有的形如 \(f(i, i)\) 的状态都是不能用于转移的,因为它们已经是末状态了。

因为钦定了末状态只出现一次,故可知末状态的期望出现次数即该状态的概率。

故有

\[f(i, j) = \sum_{k \in S(i), k \neq j} f(k, j) \times \frac{1 - p(k)} {|S(k)|} \times p(j) + \sum_{k \in S(j), k \neq i} f(i, k) \times \frac{1 - p(k)} {|S(k)|} \times p(i) + \sum_{u \in S(i), v \in S(j), u \neq v} f(u, v) \times \frac{1 - p(u)} {|S(u)|} \times \frac{1 - p(v)} {|S(v)|}
\]

显然这个转移是有后效性的,无法用简单的递推做。故考虑高斯消元,将该式转换为我们熟悉的方程形式进行求解即可。

共有 \(n ^ 2\) 只方程,时间复杂度 \(O(n ^ 6)\)。

因为一开始处于初始状态,故初始状态期望出现次数自带 \(1\)。

  1. #include <cstdio>
  2. #include <vector>
  3. using namespace std;
  4. int Abs(int x) { return x < 0 ? -x : x; }
  5. int Max(int x, int y) { return x > y ? x : y; }
  6. int Min(int x, int y) { return x < y ? x : y; }
  7. int read() {
  8. int x = 0, k = 1;
  9. char s = getchar();
  10. while (s < '0' || s > '9') {
  11. if (s == '-')
  12. k = -1;
  13. s = getchar();
  14. }
  15. while ('0' <= s && s <= '9') {
  16. x = (x << 3) + (x << 1) + (s ^ 48);
  17. s = getchar();
  18. }
  19. return x * k;
  20. }
  21. void write(int x) {
  22. if (x < 0) {
  23. putchar('-');
  24. x = -x;
  25. }
  26. if (x > 9)
  27. write(x / 10);
  28. putchar(x % 10 + '0');
  29. }
  30. void print(int x, char c) {
  31. write(x);
  32. putchar(c);
  33. }
  34. const int MAXN = 23 * 23 + 5;
  35. struct Elimination {
  36. bool free[MAXN];
  37. int n, m, rk, opt;
  38. double a[MAXN][MAXN], eps;
  39. Elimination() { eps = 1e-15; }
  40. Elimination(int N, int M) {
  41. n = N;
  42. m = M;
  43. }
  44. double Abs(double x) { return x < eps ? -x : x; }
  45. void Swap(double &x, double &y) {
  46. double t = x;
  47. x = y;
  48. y = t;
  49. }
  50. void clear() {
  51. for (int i = 1; i <= n; i++)
  52. for (int j = 1; j <= m; j++) a[i][j] = 0;
  53. }
  54. void calc() {
  55. int r = 1, c = 1;
  56. for (; r <= n && c <= m; r++, c++) {
  57. int pos = r;
  58. for (int i = r + 1; i <= n; i++)
  59. if (Abs(a[i][c]) > Abs(a[pos][c]))
  60. pos = i;
  61. if (Abs(a[pos][c]) < eps) {
  62. r--;
  63. continue;
  64. }
  65. if (pos != r)
  66. for (int i = c; i <= m; i++) Swap(a[r][i], a[pos][i]);
  67. double t;
  68. for (int i = 1; i <= n; i++)
  69. if (i != r && Abs(a[i][c]) > eps) {
  70. t = a[i][c] / a[r][c];
  71. for (int j = m; j >= c; j--) a[i][j] -= t * a[r][j];
  72. }
  73. }
  74. rk = r;
  75. }
  76. };
  77. int deg[MAXN];
  78. double p[MAXN];
  79. vector<int> mp[MAXN];
  80. void Add_Edge(int u, int v) {
  81. mp[u].push_back(v);
  82. mp[v].push_back(u);
  83. }
  84. struct node {
  85. int x, y;
  86. node() {}
  87. node(int X, int Y) {
  88. x = X;
  89. y = Y;
  90. }
  91. int Get(int n) { return (x - 1) * n + y; }
  92. };
  93. int main() {
  94. int n = read(), m = read(), x = read(), y = read();
  95. for (int i = 1, u, v; i <= m; i++) {
  96. u = read(), v = read();
  97. Add_Edge(u, v);
  98. deg[u]++, deg[v]++;
  99. }
  100. for (int i = 1; i <= n; i++) scanf("%lf", &p[i]);
  101. Elimination q;
  102. q.n = n * n;
  103. q.m = q.n + 1;
  104. q.clear();
  105. q.a[node(x, y).Get(n)][q.m] = -1;
  106. for (int i = 1; i <= n; i++)
  107. for (int j = 1; j <= n; j++) {
  108. int pos = node(i, j).Get(n);
  109. q.a[pos][pos]--;
  110. if (i != j)
  111. q.a[pos][pos] += p[i] * p[j];
  112. for (size_t k1 = 0; k1 < mp[i].size(); k1++)
  113. for (size_t k2 = 0; k2 < mp[j].size(); k2++) {
  114. int u = mp[i][k1], v = mp[j][k2];
  115. if (u == v)
  116. continue;
  117. q.a[pos][node(u, v).Get(n)] += (1 - p[u]) * (1 - p[v]) / deg[u] / deg[v];
  118. }
  119. for (size_t k = 0; k < mp[i].size(); k++)
  120. if (mp[i][k] != j)
  121. q.a[pos][node(mp[i][k], j).Get(n)] += (1 - p[mp[i][k]]) / deg[mp[i][k]] * p[j];
  122. for (size_t k = 0; k < mp[j].size(); k++)
  123. if (mp[j][k] != i)
  124. q.a[pos][node(i, mp[j][k]).Get(n)] += (1 - p[mp[j][k]]) / deg[mp[j][k]] * p[i];
  125. }
  126. q.calc();
  127. for (int i = 1; i <= n; i++)
  128. printf("%.9f\n", q.a[node(i, i).Get(n)][q.m] / q.a[node(i, i).Get(n)][node(i, i).Get(n)]);
  129. return 0;
  130. }

Solution -「CF113D」Museum的更多相关文章

  1. Solution -「构造」专练

    记录全思路过程和正解分析.全思路过程很 navie,不过很下饭不是嘛.会持续更新的(应该). 「CF1521E」Nastia and a Beautiful Matrix Thought. 要把所有数 ...

  2. Solution -「原创」Destiny

    题目背景 题目背景与题目描述无关.签到愉快. 「冷」 他半靠在床沿,一缕感伤在透亮的眼眸间荡漾. 冷见惆怅而四散逃去.经历嘈杂喧嚣,感官早已麻木.冷又见空洞而乘隙而入.从里向外,这不是感官的范畴. 他 ...

  3. Solution -「GLR-R2」教材运送

    \(\mathcal{Description}\)   Link.   给定一棵包含 \(n\) 个点,有点权和边权的树.设当前位置 \(s\)(初始时 \(s=1\)),每次在 \(n\) 个结点内 ...

  4. Solution -「WF2011」「BZOJ #3963」MachineWorks

    \(\mathcal{Description}\)   Link.   给定你初始拥有的钱数 \(C\) 以及 \(N\) 台机器的属性,第 \(i\) 台有属性 \((d_i,p_i,r_i,g_i ...

  5. Solution -「LOCAL」二进制的世界

    \(\mathcal{Description}\)   OurOJ.   给定序列 \(\{a_n\}\) 和一个二元运算 \(\operatorname{op}\in\{\operatorname{ ...

  6. Solution -「SHOI2016」「洛谷 P4336」黑暗前的幻想乡

    \(\mathcal{Description}\)   link.   有一个 \(n\) 个结点的无向图,给定 \(n-1\) 组边集,求从每组边集选出恰一条边最终构成树的方案树.对 \(10^9+ ...

  7. Solution -「LOCAL」大括号树

    \(\mathcal{Description}\)   OurTeam & OurOJ.   给定一棵 \(n\) 个顶点的树,每个顶点标有字符 ( 或 ).将从 \(u\) 到 \(v\) ...

  8. Solution -「ZJOI2012」「洛谷 P2597」灾难

    \(\mathcal{Description}\)   link.   给定一个捕食网络,对于每个物种,求其灭绝后有多少消费者失去所有食物来源.(一些名词与生物学的定义相同 w.)   原图结点数 \ ...

  9. Solution -「JSOI2008」「洛谷 P4208」最小生成树计数

    \(\mathcal{Description}\)   link.   给定带权简单无向图,求其最小生成树个数.   顶点数 \(n\le10^2\),边数 \(m\le10^3\),相同边权的边数不 ...

随机推荐

  1. 【ACM程序设计】并查集

    并查集 并查集(Union-find Sets)是一种非常精巧而实用的数据结构,它主要用于处理一些不相交集合的合并问题.一些常见的用途有:求连通子图.求最小生成树的Kruskal算法和求最近公共祖先( ...

  2. [还不会搭建博客吗?]centos7系统部署hexo博客新手入门-进阶,看这一篇就够了

    @ 目录 *本文说明 请大家务必查看 前言 首先介绍一下主角:Hexo 什么是 Hexo? 环境准备 详细版 入门:搭建步骤 安装git: 安装node: 安装Hexo: 进阶:hexo基本操作 发布 ...

  3. 4.文件共享总结上篇-Windows之间文件共享

    本文章包含上篇和下篇两部分,今天我们主要讨论Windows系统之间的文件互访 Windows系统之间文件互传 1)利用Windows自带的文件共享服务 本次试验以Win7为服务器端,win10为客户端 ...

  4. BottomNavigationView点击刷新问题

    BottomNavigationView点击刷新问题 问题: 项目中使用了BottomNavigationView作为底部导航栏. 点击item切换的时候发现会有闪烁现象出现. 原因: BottomN ...

  5. 最佳案例 | 游戏知几 AI 助手的云原生容器化之路

    作者 张路,运营开发专家工程师,现负责游戏知几 AI 助手后台架构设计和优化工作. 游戏知几 随着业务不断的拓展,游戏知几AI智能问答机器人业务已经覆盖了自研游戏.二方.海外的多款游戏.游戏知几研发团 ...

  6. 56. Merge Intervals - LeetCode

    Question 56. Merge Intervals Solution 题目大意: 一个坐标轴,给你n个范围,把重叠的范围合并,返回合并后的坐标对 思路: 先排序,再遍历判断下一个开始是否在上一个 ...

  7. 新建Vue项目记得几个配置

    1.在APP.vue文件夹中进行CSS初始化 2.下载vuex,vue-router,并配置 3.关闭语法检查vue.config.js 4.按需引入组件库

  8. 聚类--DBSCN

    1.什么是DBSCN DBSCAN也是一个非常有用的聚类算法. 它的主要优点:它不需要用户先验地设置簇的个数,可以划分具有复杂形状的簇,还可以找出不属于任何簇的点. DBSCAN比凝聚聚类和k均值稍慢 ...

  9. Public Round #1

    传送门 [PR #1]删数 题意:写的很清楚了,略 思路: 首先转化为差分数组,两个连续数相同,删掉,乘二放进去. 发现能互相转化的两个数,符号,值\(/lowbit\)都一样. 把能相互转化的数归为 ...

  10. Golang 常见设计模式之单例模式

    之前我们已经看过了 Golang 常见设计模式中的装饰和选项模式,今天要看的是 Golang 设计模式里最简单的单例模式.单例模式的作用是确保无论对象被实例化多少次,全局都只有一个实例存在.根据这一特 ...