Codeforces 446D - DZY Loves Games(高斯消元+期望 DP+矩阵快速幂)
神仙题,%%%
首先考虑所有格子都是陷阱格的情况,那显然就是一个矩阵快速幂,具体来说,设 \(f_{i,j}\) 表示走了 \(i\) 步到达 \(j\) 点的概率,那显然有 \(dp_{i+1,k}\leftarrow dp_{i,j}\times\dfrac{1}{\delta^+(j)}\)(\(j,k\) 之间有边相连),矩阵快速幂优化一下即可,最终答案即为 \(f_{k-1,n}\),时间复杂度 \(n^3\log k\)。
接下来考虑原题,注意到本题 \(n\) 的数据范围为 \(500\),\(500^3\log k\) 过不了,但是陷阱格的数据范围只有 \(101\),\(101^3\log k\) 刚好能过,这启示我们可以以陷阱格为状态采用类似的方式进行矩阵快速幂。下设陷阱格个数为 \(m\),我们将所有陷阱格编个号,\(x_1,x_2,\cdots,x_m\),我们记 \(p_{i,j}\) 表示从第 \(i\) 个陷阱格出发,在不经过其他陷阱格的情况到达第 \(j\) 个陷阱格的概率,再设 \(f_{i,j}\) 表示已经经过了 \(i\) 个陷阱格,现在在第 \(j\) 个陷阱格的概率。倘若我们已经知道了 \(p_{i,j}\),那么显然有 \(f_{i+1,k}\leftarrow f_{i,j}\times p_{j,k}\),刚好矩阵快速幂。
考虑怎样求 \(p_{i,j}\),我们考虑再令 \(g_{i,j}\) 表示当前在 \(i\) 号点,有多大概率能过从 \(i\to j\),满足 \(i=x_j\) 或者路径上除第 \(j\) 个陷阱格外不存在其他陷阱格,那么就有 \(p_{i,j}=\sum\limits_{(x_i,t)\in E}g_{t,j}\times\dfrac{1}{\delta^+(x_i)}\)。最后考虑求 \(g_{i,j}\),显然若 \(i\) 本身就是陷阱格,那只有 \(i=x_j\) 时 \(g_{i,j}=1\),其他情况下 \(g_{i,j}=0\) 了。否则枚举下一个点进行转移,即 \(g_{i,j}=\sum\limits_{(i,k)\in E}g_{k,j}\times\dfrac{1}{\delta^+(i)}\),显然这个东西不能当作 DP 方程进行转移,因为它存在后效性,但注意到这题 \(n\) 只有 \(500\),刚好放 \(n^3\) 过,因此考虑高斯消元。不过对于所有的 \(j\) 都消一遍复杂度高达 \(mn^3\),无法通过,但稍加观察即可注意到这 \(nm\) 个方程中,所有 \(i\) 相同的方程除了常数项,前面的系数没有区别,因此考虑按照 CF832E 的套路,前面的系数列不是一列而是 \(m\) 列,相当于将增广矩阵由 \(n\times (n+1)\) 变为 \(n\times (n+m)\),这样复杂度即可讲到三方级别。
总复杂度 \(n^3+m^3\log k\)。
#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define fill0(a) memset(a,0,sizeof(a))
#define fill1(a) memset(a,-1,sizeof(a))
#define fillbig(a) memset(a,63,sizeof(a))
#define pb push_back
#define ppb pop_back
#define mp make_pair
template<typename T1,typename T2> void chkmin(T1 &x,T2 y){if(x>y) x=y;}
template<typename T1,typename T2> void chkmax(T1 &x,T2 y){if(x<y) x=y;}
typedef pair<int,int> pii;
typedef long long ll;
typedef unsigned int u32;
typedef unsigned long long u64;
namespace fastio{
#define FILE_SIZE 1<<23
char rbuf[FILE_SIZE],*p1=rbuf,*p2=rbuf,wbuf[FILE_SIZE],*p3=wbuf;
inline char getc(){return p1==p2&&(p2=(p1=rbuf)+fread(rbuf,1,FILE_SIZE,stdin),p1==p2)?-1:*p1++;}
inline void putc(char x){(*p3++=x);}
template<typename T> void read(T &x){
x=0;char c=getchar();T neg=0;
while(!isdigit(c)) neg|=!(c^'-'),c=getchar();
while(isdigit(c)) x=(x<<3)+(x<<1)+(c^48),c=getchar();
if(neg) x=(~x)+1;
}
template<typename T> void recursive_print(T x){if(!x) return;recursive_print(x/10);putc(x%10^48);}
template<typename T> void print(T x){if(!x) putc('0');if(x<0) putc('-'),x=~x+1;recursive_print(x);}
void print_final(){fwrite(wbuf,1,p3-wbuf,stdout);}
}
const int MAXN=500;
const int MAXM=101;
const int TOT=601;
int n,m,k,deg[MAXN+5],num[MAXN+5][MAXN+5];
bool is[MAXN+5];int rm[MAXN+5],id[MAXN+5],cnt=0;
double a[MAXN+5][TOT+5],f[MAXN+5][MAXM+5];
struct mat{
double a[MAXM+5][MAXM+5];
mat(){for(int i=1;i<=MAXM;i++) for(int j=1;j<=MAXM;j++) a[i][j]=0;}
mat operator *(const mat &rhs){
mat ret;
for(int i=1;i<=cnt;i++) for(int j=1;j<=cnt;j++)
for(int l=1;l<=cnt;l++) ret.a[i][j]+=a[i][l]*rhs.a[l][j];
return ret;
}
};
int main(){
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=n;i++){
scanf("%d",&is[i]);
if(is[i]) rm[++cnt]=i,id[i]=cnt;
}
for(int i=1,u,v;i<=m;i++){
scanf("%d%d",&u,&v);deg[u]++;deg[v]++;
num[u][v]++;num[v][u]++;
}
// for(int i=1;i<=n;i++) printf("%d\n",deg[i]);
for(int i=1;i<=n;i++){
if(!is[i]){
a[i][i]=-1;
for(int j=1;j<=n;j++) if(i^j)
a[i][j]=1.0*num[i][j]/deg[i];
} else {
a[i][i]=a[i][id[i]+n]=1;
}
}
// for(int i=1;i<=n;i++) for(int j=1;j<=n+cnt;j++)
// printf("%.10lf%c",a[i][j],(j==n+cnt)?'\n':' ');
for(int i=1;i<=n;i++){
int pos=i;
for(int j=i+1;j<=n;j++) if(fabs(a[j][i])>fabs(a[pos][i])) pos=j;
for(int j=i;j<=n+cnt;j++) swap(a[pos][j],a[i][j]);
for(int j=i+1;j<=n+cnt;j++) a[i][j]/=a[i][i];a[i][i]=1;
for(int j=i+1;j<=n;j++){
for(int k=i+1;k<=n+cnt;k++) a[j][k]-=a[i][k]*a[j][i];
a[j][i]=0;
}
}
for(int i=1;i<=cnt;i++) for(int j=n;j;j--){
f[j][i]=a[j][i+n];
for(int k=j+1;k<=n;k++) f[j][i]-=a[j][k]*f[k][i];
// printf("%d %d %.10lf\n",j,i,f[j][i]);
} mat trs,ini,mul;
for(int i=1;i<=cnt;i++) for(int j=1;j<=cnt;j++){
for(int l=1;l<=n;l++) trs.a[j][i]+=1.0*num[rm[i]][l]/deg[rm[i]]*f[l][j];
// printf("%d %d %.10lf\n",i,j,trs.a[i][j]);
}
for(int i=1;i<=cnt;i++) ini.a[i][1]=f[1][i];
k-=2;for(int i=1;i<=cnt;i++) mul.a[i][i]=1;
for(;k;k>>=1,trs=trs*trs) if(k&1) mul=mul*trs;
ini=mul*ini;printf("%.10lf\n",ini.a[cnt][1]);
return 0;
}
Codeforces 446D - DZY Loves Games(高斯消元+期望 DP+矩阵快速幂)的更多相关文章
- 【CF446D】DZY Loves Games 高斯消元+矩阵乘法
[CF446D]DZY Loves Games 题意:一张n个点m条边的无向图,其中某些点是黑点,1号点一定不是黑点,n号点一定是黑点.问从1开始走,每次随机选择一个相邻的点走过去,经过恰好k个黑点到 ...
- BZOJ_3270_博物馆_(高斯消元+期望动态规划+矩阵)
描述 http://www.lydsy.com/JudgeOnline/problem.php?id=3270 \(n\)个房间,刚开始两个人分别在\(a,b\),每分钟在第\(i\)个房间有\(p[ ...
- BZOJ 1778: [Usaco2010 Hol]Dotp 驱逐猪猡(高斯消元+期望dp)
传送门 解题思路 设\(f(x)\)表示到\(x\)这个点的期望次数,那么转移方程为\(f(x)=\sum\frac{f(u)*(1 - \frac{p}{q})}{deg(u)}\),其中\(u\) ...
- 高斯消元+期望dp——light1151
高斯消元弄了半天没弄对.. #include<bits/stdc++.h> using namespace std; #define maxn 205 #define eps 1e-8 d ...
- HDU2262;Where is the canteen(高斯消元+期望)
传送门 题意 给出一张图,LL从一个点等概率走到上下左右位置,询问LL从宿舍走到餐厅的步数期望 分析 该题是一道高斯消元+期望的题目 难点在于构造矩阵,我们发现以下结论 设某点走到餐厅的期望为Ek 1 ...
- codeforces E. Okabe and El Psy Kongroo(dp+矩阵快速幂)
题目链接:http://codeforces.com/contest/821/problem/E 题意:我们现在位于(0,0)处,目标是走到(K,0)处.每一次我们都可以从(x,y)走到(x+1,y- ...
- Codeforces Gym10008E Harmonious Matrices(高斯消元)
[题目链接] http://codeforces.com/gym/100008/ [题目大意] 给出 一个n*m的矩阵,要求用0和1填满,使得每个位置和周围四格相加为偶数,要求1的数目尽量多. [题解 ...
- Codeforces 832E Vasya and Shifts - 高斯消元
题目传送门 快速的传送门I 快速的传送门II 题目大意 (题意比较复杂,请自行阅读原题) 可以将原题的字母都看成它们的在字符表中的下标,这样问题就变成给定$n$个$m$维向量$\vec{a_{1}}, ...
- POJ1487 Single-Player Games 高斯消元
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - POJ1487 题解概括 给出多个树形结构,由小写字母和数字表示,每个小写字母表示一棵小树.现在,以a为根节点 ...
随机推荐
- 【Java虚拟机4】Java内存模型(硬件层面的并发优化基础知识--缓存一致性问题)
前言 今天学习了Java内存模型第一课的视频,讲了硬件层面的知识,还是和大学时一样,醍醐灌顶.老师讲得太好了. Java内存模型,感觉以前学得比较抽象.很繁杂,抽象. 这次试着系统一点跟着2个老师学习 ...
- Coursera Deep Learning笔记 序列模型(一)循环序列模型[RNN GRU LSTM]
参考1 参考2 参考3 1. 为什么选择序列模型 序列模型能够应用在许多领域,例如: 语音识别 音乐发生器 情感分类 DNA序列分析 机器翻译 视频动作识别 命名实体识别 这些序列模型都可以称作使用标 ...
- [no code][scrum meeting] Alpha 11
项目 内容 会议时间 2020-04-17 会议主题 OCR紧急技术风险分析 会议时长 30min 参会人员 PM+OCR组成员 $( "#cnblogs_post_body" ) ...
- (三)、Docker常用基础命令
1.Docker 帮助命令 帮助命令: docker version 查看版本 docker info 查询docker详细信息 docker --help 查看命令帮助 2.Docker 镜像命令 ...
- Noip模拟16 2021.7.15
题目真是越来越变态了 T1 Star Way To Heaven 首先,你要看出这是一个最小生成树的题(妙吧?) 为什么可以呢? 我们发现从两点连线的中点过是最优的,但是上下边界怎么办呢? 我们把上下 ...
- TCP 拥塞窗口原理
学过网络相关课程的,都知道TCP中,有两个窗口: 滑动窗口(在我们的上一篇文章中有讲),接收方通过通告发送方自己的可以接受缓冲区大小(这个字段越大说明网络吞吐量越高),从而控制发送方的发送速度. 拥塞 ...
- UVM RAL模型和内置seq
转载:UVM RAL模型:用法和应用_寄存器 (sohu.com) 在系统设计中通常会面临两大挑战:缩小技术节点的规模和上市时间(TTM,Time to Market).为了适应激烈的市场竞争,大多数 ...
- ASP的调试技术解答
一. 调试 ASP.NET 应用程序时出现"未将项目配置为进行调试"的错误信息 症状 当您在 Visual Studio .NET 中调试 ASP.NET 应用程序时,可能会出现下 ...
- usb设备无法识别
之前用飞线用旧板子飞线连接了一个wifi模块到usb0口上,调试ok的,现在新设计的板子回来了,wifi模块是连接在usb2口上的,系统起来后发现wlan0不存在,用lsusb查看wifi模块的usb ...
- xiaoxiaole
common.cpp #include "common.h" common.h #ifndef COMMON_H_INCLUDED #define COMMON_H_INCLUDE ...