【高斯消元】兼 【期望dp】例题
【总览】
高斯消元基本思想是将方程式的系数和常数化为矩阵,通过将矩阵通过行变换成为阶梯状(三角形),然后从小往上逐一求解。
如:$3X_1 + 2X_2 + 1X_3 = 3$
$ X_2 + 2X_3 = 1$
$2X_1 + X_3 = 0$
化为矩阵为:
--->
----->
----->
然后就可以通过最后一行直接求出$X_3 = ...$,将其带回第二行,算出$X_2$,同理算出$X_1$。
代码很好理解:
inline void gauss(){
int i, j, k, l;
for(i = ; i <= n; i++){
l = i;
for(j = i + ; j <= n; j++)
if(fabs(matrix[j][i]) > fabs(matrix[l][i])) l = j;
if(l != i) for(j = i; j <= n + ; j++)
swap(matrix[i][j], matrix[l][j]);
for(j = i + ; j <= n; j++){
double tmp = matrix[j][i] / matrix[i][i];
for(k = i; k <= n + ; k++)
matrix[j][k] -= matrix[i][k] * tmp;
}
}
for(i = n; i >= ; i--){
double t = matrix[i][n + ];
for(j = n; j > i; j--)
t -= ans[j] * matrix[i][j];
ans[i] = t / matrix[i][i];
}
}
高斯消元最常应用在 期望DP 中。下面是几道例题。
【BZOJ1013】球形空间产生器sphere
由给出的$n + 1$个坐标,可以列出 $n$个方程,剩下的模板。
【CODE】
#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<vector>
#include<cmath>
using namespace std; const int N = ;
double matrix[N][N], last[N], t, ans[N];
int n; inline int read(){
int i = , f = ; char ch = getchar();
for(; (ch < '' || ch > '') && ch != '-'; ch = getchar());
if(ch == '-') f = -, ch = getchar();
for(; ch >= '' && ch <= ''; ch = getchar())
i = (i << ) + (i << ) + (ch -'');
return i * f;
} inline void wr(int x){
if(x < ) putchar('-'), x = -x;
if(x > ) wr(x / );
putchar(x % + '');
} inline void gauss(){
int i, j, l, k;
for(i = ; i <= n; i++){
l = i;
for(j = i + ; j <= n; j++)
if(fabs(matrix[j][i]) > fabs(matrix[l][i])) l = j;
if(l != i) for(j = i; j <= n + ; j++)
swap(matrix[i][j], matrix[l][j]);
for(j = i + ; j <= n; j++){
double tmp = matrix[j][i] / matrix[i][i];
for(k = i; k <= n + ; k++)
matrix[j][k] -= matrix[i][k] * tmp;
}
}
for(i = n; i >= ; i--){
double tmp = matrix[i][n + ];
for(j = n; j > i; j--)
tmp -= ans[j] * matrix[i][j];
ans[i] = tmp / matrix[i][i];
}
} int main(){
n = read();
for(int i = ; i <= n; i++) scanf("%lf", &last[i]);
for(int i = ; i <= n; i++){
t = ;
for(int j = ; j <= n; j++){
double tmp; scanf("%lf", &tmp);
matrix[i][j] = * (tmp - last[j]);
t += tmp * tmp - last[j] * last[j];
last[j] = tmp;
}
matrix[i][n + ] = t;
}
gauss();
for(int i = ; i <= n; i++){
if(i < n) printf("%.3lf ", ans[i]);
else printf("%.3lf\n", ans[i]);
}
return ;
}
【BZOJ3143】游走
因为要求期望的最小值,那么走的次数多的边肯定要让花费(编号)尽可能小,所以可以先求出从每个点出发次数的期望值$E_i$,那么对于一条边而言,走这条边的期望次数就是$E_i / degree[i] + E_j / degree[j]$,只要排一遍序就好。
求点的期望:$E_i = \sum (E_{son[i]} / degree[i])$
【code】
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
#include<vector>
#define eps 1e-10
using namespace std; const int N = ;
double matrix[N][N], ans[N], ret;
int n, m, num, degree[N];
int st[], ed[];
double gg[]; inline void addEdge(const int &u, const int &v){
degree[u]++;
degree[v]++;
st[++num] = u, ed[num] = v;
} inline int read(){
int i = , f = ; char ch = getchar();
for(; (ch < '' || ch > '') && ch != '-'; ch = getchar());
if(ch == '-') f = -, ch = getchar();
for(; ch >= '' && ch <= ''; ch = getchar())
i = (i << ) + (i << ) + (ch -'');
return i * f;
} inline void gauss(){
int i, j, l, k;
for(i = ; i <= n; i++){
l = i;
for(j = i + ; j <= n; j++)
if(fabs(matrix[j][i]) > fabs(matrix[l][i])) l = j;
if(l != i) for(j = i; j <= n + ; j++)
swap(matrix[i][j], matrix[l][j]);
for(j = i + ; j <= n; j++){
double tmp = matrix[j][i] / matrix[i][i];
for(k = i; k <= n + ; k++)
matrix[j][k] -= matrix[i][k] * tmp;
}
}
for(i = n; i >= ; i--){
double tmp = matrix[i][n + ];
for(j = n; j > i; j--)
tmp -= ans[j] * matrix[i][j];
ans[i] = tmp / matrix[i][i];
}
} inline bool cmp (double a, double b){
return a > b;
} int main(){
n = read(), m = read();
for(int i = ; i <= m; i++){
int u = read(), v = read();
addEdge(u, v);
}
int i, j;
for(i = ; i <= m; i++){
matrix[st[i]][ed[i]] += 1.0 /degree[ed[i]];
matrix[ed[i]][st[i]] += 1.0 /degree[st[i]];
}
for(i = ; i <= n; i++) matrix[n][i] = ;
for(i = ; i <= n; i++) matrix[i][i] = -1.0;
matrix[][n + ] = -1.0;
gauss();
for(i = ; i <= m; i++)
gg[i] = ans[st[i]] / degree[st[i]] + ans[ed[i]] / degree[ed[i]];
sort(gg + , gg + m + , cmp);
for(i = ; i <= m; i++) ret += gg[i] * i;
printf("%.3f\n", ret);
return ;
}
【bzoj2337】XOR和路径
学到了!看见求异或和$----->$按位计算:即一位一位的计算答案每一位上为1的期望值,这样就可以轻松统计出答案。
每一位都要重新构造矩阵求期望,设$a[i]$表示从$i$到$n$的路径异或和(这一位)为$1$的期望概率(总是≤$1$)
对于当前第$i + 1$位,若$(dis >> i) \& 1$(这一位为1),那么要异或和为$1$,要求他从关联点异或和为$0$转移来,
同理,若这一位为$0$,要求从$1$转移来。即:$$a[i] = \sum a[son[i]](dis这一位为0) / degree[i] + \sum a[son[i]](dis这一位为1) / degree[i]$$。
【code】
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cmath>
using namespace std; const int N = , M = ;
int n, m;
int ecnt, st[M << ], ed[M << ], len[M << ], degree[N];
double matrix[N][N], ans[N], ret; inline void addEdge(const int &u, const int &v, const int &l){
st[++ecnt] = u, ed[ecnt] = v, len[ecnt] = l; degree[u]++;
if(u != v) st[++ecnt] = v, ed[ecnt] = u, len[ecnt] = l, degree[v]++;
} inline void gauss(){
int i, j, k, l;
for(i = ; i <= n; i++){
l = i;
for(j = i + ; j <= n; j++)
if(fabs(matrix[j][i]) > fabs(matrix[l][i])) l = j;
if(l != i) for(j = i; j <= n + ; j++)
swap(matrix[i][j], matrix[l][j]);
for(j = i + ; j <= n; j++){
double tmp = matrix[j][i] / matrix[i][i];
for(k = i; k <= n + ; k++)
matrix[j][k] -= matrix[i][k] * tmp;
}
}
for(i = n; i >= ; i--){
double t = matrix[i][n + ];
for(j = n; j > i; j--)
t -= ans[j] * matrix[i][j];
ans[i] = t / matrix[i][i];
}
} int main(){
scanf("%d%d", &n, &m);
int i, j, k;
for(i = ; i <= m; i++){
int u, v, w; scanf("%d%d%d", &u, &v, &w);
addEdge(u, v, w);
}
for(i = ; i <= ; i++){
memset(matrix, , sizeof matrix);
memset(ans, , sizeof ans);
for(j = ; j <= n; j++) matrix[j][j] = ;
for(j = ; j <= ecnt; j++){
int l = len[j], u = st[j], v = ed[j];
if(u == n) continue;
if((l >> i) & ){
matrix[u][v] += 1.0 / degree[u];
matrix[u][n + ] += 1.0 / degree[u];
}
else matrix[u][v] -= 1.0 / degree[u];
}
gauss();
ret += ans[] * ( << i);
}
printf("%.3f\n", ret);
return ;
}
【高斯消元】兼 【期望dp】例题的更多相关文章
- 高斯消元与期望DP
高斯消元可以解决一系列DP序混乱的无向图上(期望)DP DP序 DP序是一道DP的所有状态的一个排列,使状态x所需的所有前置状态都位于状态x前: (通俗的说,在一个状态转移方程中‘=’左侧的状态应该在 ...
- LOJ 2542 「PKUWC2018」随机游走 ——树上高斯消元(期望DP)+最值反演+fmt
题目:https://loj.ac/problem/2542 可以最值反演.注意 min 不是独立地算从根走到每个点的最小值,在点集里取 min ,而是整体来看,“从根开始走到点集中的任意一个点就停下 ...
- HDU4870_Rating_双号从零单排_高斯消元求期望
原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=4870 原题: Rating Time Limit: 10000/5000 MS (Java/Other ...
- hdu 4870 rating(高斯消元求期望)
Rating Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Sub ...
- Luogu3232 HNOI2013 游走 高斯消元、期望、贪心
传送门 这种无向图上从一个点乱走到另一个点的期望题目好几道与高斯消元有关 首先一个显然的贪心:期望经过次数越多,分配到的权值就要越小. 设$du_i$表示$i$的度,$f_i$表示点$i$的期望经过次 ...
- 【BZOJ3143】【HNOI2013】游走 && 【BZOJ3270】博物馆 【高斯消元+概率期望】
刚学完 高斯消元,我们来做几道题吧! T1:[BZOJ3143][HNOI2013]游走 Description 一个无向连通图,顶点从1编号到N,边从1编号到M. 小Z在该图上进行随机游走,初始时小 ...
- loj2542 「PKUWC2018」随机游走 MinMax 容斥+树上高斯消元+状压 DP
题目传送门 https://loj.ac/problem/2542 题解 肯定一眼 MinMax 容斥吧. 然后问题就转化为,给定一个集合 \(S\),问期望情况下多少步可以走到 \(S\) 中的点. ...
- 【BZOJ-3143】游走 高斯消元 + 概率期望
3143: [Hnoi2013]游走 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2264 Solved: 987[Submit][Status] ...
- 【BZOJ-3270】博物馆 高斯消元 + 概率期望
3270: 博物馆 Time Limit: 30 Sec Memory Limit: 128 MBSubmit: 292 Solved: 158[Submit][Status][Discuss] ...
- [ACM] hdu 4418 Time travel (高斯消元求期望)
Time travel Problem Description Agent K is one of the greatest agents in a secret organization calle ...
随机推荐
- C++ #if #endif #define #ifdef #ifndef #if defined #if !defined详解 (转)
(源)http://blog.csdn.net/sky1203850702/article/details/42024673 首先,让我们先从头文件开始,在很多头文件里,我们会看到这样的语句 #ifn ...
- blog界面自己写了css,参考了网站设计,想要的自己拿
junhey这就把界面的代码公布下来,可以自己修改额~(ps:麻烦加个友链http://www.cnblogs.com/junhey/ 谢谢) /* 初始化样式 */ html, body, div, ...
- 【Selenium】idea的selenium环境配置
1.maven配置 下载地址:http://maven.apache.org/download.cgi# 下载内容:apache-maven-3.5.0-bin.zip 环境变量:M2_HOME:E: ...
- CentOS升级Python2.7导致使用pip等命令安装模块失败
报错如下: # pip Traceback (most recent call last): File , in <module> from pkg_resources import lo ...
- Work Time Manager【开源项目】- 创建自己日志组件 2.0重构
Hello all , 我又回来了 这次我们真是开始来聊聊开源项目里,小而有用的模块或者组件的开发思想. 同时,软件已经更新到1.60的版本了,支持新用户注册,可以不再使用统一的test账户了. 您可 ...
- Mac下终端配置(item2 + oh-my-zsh + solarized配色方案)
最近重装了系统,于是便重新配置了一下终端,使其更符合用户习惯. 效果如下: 拥有语法高亮,命令行tab补全,自动提示符,显示Git仓库状态等功能. 安装 首先我们下载的 iTem2 这个软件,比Mac ...
- XWindow启动流程
X Window系统架构 一.基本概念: 1.X Client:X客户端,运行在远端主机上 X Client最重要的工作就是处理来自 X Server 的动作,将该动作处理成为绘图数据, 再将这些绘图 ...
- RSA加密通信小结(四)--RSA加解密的实际操作与流程小结
在上一篇文章中,我们已经将密钥的生成方法和流程,归纳总结.而本篇主要是讲如何利用密钥进行加解密. 首先,在上一篇文章中的我们生成了很多密钥,证书等等. 在上述生成的文件中,接收服务端加密报文:pkcs ...
- Swift3 访问权限fileprivate和 open
在swift 3中新增加了两种访问控制权限 fileprivate和 open. 下面结合网上资料和个人理解整理一下两个属性的原理与介绍. fileprivate 在原有的swift中的 privat ...
- Linux 中最常用的目录及文件管理命令
一.查看文件的命令 对于一个文本文件,在linux中有多种查看方式来获知文件内容,如直接显示整个文本内容.分页查看内容.或者只查看文件开头或末尾的部分内容.在linux可以用不同的命令来实现. 1. ...