首页 > 其他分享 >CodeForces 605E Intergalaxy Trips 题解

CodeForces 605E Intergalaxy Trips 题解

时间:2023-06-27 09:33:30浏览次数:46  
标签:le 605E 题解 blog int https Intergalaxy com 转移

题意

有一张 \(n\) 个点的有向完全图,边 \(i \to j\) 有 \(p_{i,j}\) 的概率出现(\(p_{i,i}=1\))。你要从 \(1\) 开始,每天可以走一条出边或留在原地,求最优策略下走到 \(n\) 的期望天数。输出小数(不取模)。
\(n \le 10^3\)

思路

设 \(f(i)\) 表示从 \(i\) 走到 \(n\) 的期望天数,那么答案就是 \(f(1)\)。接下来考虑怎么计算 \(f\)。

首先考虑怎么转移 \(f\)。
考虑当前我们在 \(i\),下一步要去 \(j(1\le j\le n)\)(\(j\) 可以等于 \(i\))。因为要算最优方案,所以当我们选择去 \(j\) 的时候,一定满足所有优于 \(j\) 的点都没有边。
现在就可以把方程写出来了:

\[f(i)=1+\sum_{j=1}^n f(j)p_{i,j}\prod_{1\le k\le n}^{f(k)<f(j)}(1-p_{i,k}) \]

但是这个式子需要依赖已经计算好的 \(f\),所以还是没法做。
我们观察发现,由于 \(p_{i,i}=1\),所以对于所有满足 \(f(j)>f(i)\) 的 \(j\),后面的那个 \(\prod_{1\le k\le n}^{f(k)<f(j)}(1-p_{i,k})\) 一定会包含 \(k=i\) 的一项,也就是 \(1-p_{i,i}=0\)。换句话说,这样的 \(j\) 一定对 \(i\) 没有贡献。
其实还有另一种解释,因为我们总是可以原地停留的,所以我们不可能从 \(f\) 较小的走向 \(f\) 较大的,这样明显不如原地停留优秀。
所以,\(f\) 总是会从较小的往较大的转移。也就是说,把原地停留的情况移项过后,\(f\) 的转移就是一个 DAG

先把移项过后的式子写出来:

\[f(i)=\frac{1+\sum_{1\le j\le n}^{f(j)<f(i)} f(j)p_{i,j}\prod_{1\le k\le n}^{f(k)<f(j)}(1-p_{i,k})}{1-\sum_{1\le j\le n}^{f(j)<f(i)}(1-p_{i,j})} \]

现在考虑怎么找出 DAG 的形态。
首先 \(f(n)=0\) 肯定是最小的 \(f\)。然后我们用 \(f(n)\) 去转移其它的点(也就是作为式子里的 \(j\))。这个时候每个点都有一个当前的 \(f\)(仅考虑 \(u \to n\) 的边计算得来的 \(f\))了。我们把当前的 \(f\) 记为 \(f'\)。
考虑这些 \(f'\) 中最小的那一个,假设是 \(f'(i)\)。可以证明,此时 \(f(i)=f'(i)\)(证明在下面)。所以这时我们就算出了 \(f(i)\)。然后继续用 \(f(i)\) 去转移其它的点,然后再在剩下的点里面找出当前 \(f\) 最小的,假设是 \(f''(k)\)。按照类似的证明我们知道 \(f''(k)=f(k)\)。以此类推,就可以找出 DAG 形态并算出答案了。总复杂度 \(O(n^2)\)。

现在我们证明 \(f(i)=f'(i)\)。(对于其它的也类似)
首先发现一个性质,对于任意时刻的 \(f'\) 来说(不只是最终答案的 \(f\)),如果用 \(f'(j)\) 转移到 \(f'(i)\),那么一定满足 \(f'(i)\ge f'(j)\)。因为我们是从 \(i\) 走到 \(j\) 的,那 \(i\) 的步数肯定要多一步,所以不可能比 \(j\) 小。严谨证明就是如果 \('(j) \ge f'(i)\),那么可以继续用 \(i\) 去转移到 \(j\),这样 \(f'(i)\) 和 \(f'(j)\) 就会要么越来越小,要么相等。如果相等那么结论得证;如果越来越小那么显然矛盾。
然后就很简单了,因为 \(f'(i)\) 是除 \(f(n)\)(或者那些已经转移过其它点的点)以外最小的,而比 \(f'(i)\) 小的已经转移到 \(i\) 过了,所以不可能有其它的点转移到 \(i\) 使 \(f'(i)\) 更小了。如果让 \(f'(i)\) 更大显然是不优的,所以 \(f'(i) = f(i)\)。

代码

代码其实很好写。

代码
#include <bits/stdc++.h>

const int N = 1e3 + 5;

int n;
double p[N][N];

double f[N], g[N], h[N];

bool done[N];
void trans(int j, int i) { g[i] += p[i][j] * f[j] * h[i], h[i] *= 1 - p[i][j], f[i] = g[i] / (1 - h[i]); }

int main() {
	scanf("%d", &n);
	for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) { int x; scanf("%d", &x); p[i][j] = x / 100.0; }
	for(int i = 1; i <= n; i++) f[i] = g[i] = h[i] = 1;
	done[n] = true, f[n] = 0;
	for(int i = 1; i <= n; i++) if(!done[i]) trans(n, i);
	for(int _ = 2; _ <= n; _++) {
		int now = 0;
		double val = 1e18;
		for(int i = 1; i <= n; i++) if(!done[i] && f[i] < val) now = i, val = f[i];
		done[now] = true;
		for(int i = 1; i <= n; i++) if(!done[i]) trans(now, i);
	}
	printf("%.6lf\n", f[1]);
	return 0;
}

参考资料

https://www.luogu.com.cn/blog/SDNetFriend/solution-cf605e
https://www.luogu.com.cn/blog/LCA/solution-cf605e
https://www.luogu.com.cn/blog/user33243/solution-cf605e
https://codeforces.com/blog/entry/22019

标签:le,605E,题解,blog,int,https,Intergalaxy,com,转移
From: https://www.cnblogs.com/xxeray/p/codeforces-605e.html

相关文章

  • P3387 【模板】缩点 题解
    一、题目描述:给你一个$n$个点,$m$条边的有向图。点带权。求一条路径经过的所有点的权值和最大是多少。点可以重复经过。数据范围:$1\len\le1\times10^4,1\lem\le1\times10^5$。 二、解题思路:缩点板子题,不需要思路。时间复杂度$O(n+m)$。......
  • 复旦大学2022--2023学年第二学期(22级)高等代数II期末考试第八大题解答
    八、(10分) 设$n$阶实方阵$A$满足$A^3=A$,证明: 若对任意的实列向量$x$,均有$x'A'Ax\leqx'x$,则$A$是实对称阵.证法一(几何证法) 将题目转换成几何语言:设$\varphi$是$n$维欧氏空间$V$上的线性算子,满足$\varphi^3=\varphi$,若对$V$中任一向量$v......
  • P3388 【模板】割点(割顶) 题解
    一、题目描述:给你一个$n$个点,$m$条边的无向图。求出所有割点,按节点编号升序排序。数据范围:$1\len\le2\times10^4,1\lem\le1\times10^5$。 二、解题思路:板子题,不需要思路。时间复杂度$O(n+m)$。 三、完整代码:1#include<iostream>......
  • 【问题解决】echart formatter 模板变量 精度
    遇到这样的精度问题这是之前的配置formatter:`{serie|{a}}\n{data|{c}}`+this.label,这样实现了不同样式,出现了jsnumber类型的精度问题formatter也可以返回模板,返回样式|模板的形式formatter:function(data){return(......
  • 缓存与DB数据一致性问题解决的几个思路
    使用缓存必然会碰到缓存跟真实数据不一致的问题,虽然我们会在数据发生变化时通知缓存,但是这个延迟时间内必然会导致数据不一致,如何解决一般有下面几个思路:首先,当这个延迟如果在业务上时可以接受的,比如文章阅读、评论次数这样的缓存数据,这样的问题这里不考虑。 类似数据库分布式事务......
  • docker 安装 jenkins 以及安装插件出现的问题解决方式
    使用docker-composeversion:"3.9"services:jenkins:image:jenkins/jenkins:lts-jdk11ports:-"8080:8080"-"5000:5000"volumes:-/root/software/jenkins/jenkins-data:/var/jenkins_homeenvir......
  • D Odd Queries 题解
    原题传送门题意简述给定一个数组,再给出m个各自独立(即这个操作不影响后续的询问)的询问,每次给定一个区间,询问将这个区间每个元素都修改为k后,数组总和会是奇数吗?解决思路由于n的范围很大,所以暴力肯定是不可以了,由于每个询问是独立的,我们不需要修改序列,所以不需要使用数据结构。......
  • 01 矩阵题解
    DescirptionSolution若定义\(f(k)\)为一行有\(k\)个\(1\)的方案数,则\(\displaystylef(k)=\binom{m}{k}x^ky^{m-k}\)。则\(\displaystyleE=\sum_{i=0}^{m}i\sum_{j=1}^{n}\binom{n}{j}f(i)^j\left(\sum_{k=i+1}^{m}f(k)\right)^{n-j}\)。不妨设\(\display......
  • CF321C Ciel the Commander 题解 点分治
    题目链接:http://codeforces.com/problemset/problem/321/C解题思路:点分治模板题。每次找到重心给他分配一个字符,分治往下走的时候分配的字符ASCII码\(+1\)即可。示例程序:#include<bits/stdc++.h>usingnamespacestd;constintmaxn=1e5+5;vector<int>g[maxn];i......
  • 洛谷P4178 Tree 题解 树上点分治
    题目链接:https://www.luogu.com.cn/problem/P4178解题思路:点分治模板题。设当前重心为\(u\),一共有三种不同类型的路径:路径的一个端点恰好是重心\(u\);路径的两个端点在\(u\)的不同子树中;路径的两个端点在\(u\)的同一个子树中。找到重心\(u\)之后,前两类路径分开求......