Codeforces 题目传送门 & 洛谷题目传送门

神仙题,%%%

首先考虑所有格子都是陷阱格的情况,那显然就是一个矩阵快速幂,具体来说,设 \(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+矩阵快速幂)的更多相关文章

  1. 【CF446D】DZY Loves Games 高斯消元+矩阵乘法

    [CF446D]DZY Loves Games 题意:一张n个点m条边的无向图,其中某些点是黑点,1号点一定不是黑点,n号点一定是黑点.问从1开始走,每次随机选择一个相邻的点走过去,经过恰好k个黑点到 ...

  2. BZOJ_3270_博物馆_(高斯消元+期望动态规划+矩阵)

    描述 http://www.lydsy.com/JudgeOnline/problem.php?id=3270 \(n\)个房间,刚开始两个人分别在\(a,b\),每分钟在第\(i\)个房间有\(p[ ...

  3. BZOJ 1778: [Usaco2010 Hol]Dotp 驱逐猪猡(高斯消元+期望dp)

    传送门 解题思路 设\(f(x)\)表示到\(x\)这个点的期望次数,那么转移方程为\(f(x)=\sum\frac{f(u)*(1 - \frac{p}{q})}{deg(u)}\),其中\(u\) ...

  4. 高斯消元+期望dp——light1151

    高斯消元弄了半天没弄对.. #include<bits/stdc++.h> using namespace std; #define maxn 205 #define eps 1e-8 d ...

  5. HDU2262;Where is the canteen(高斯消元+期望)

    传送门 题意 给出一张图,LL从一个点等概率走到上下左右位置,询问LL从宿舍走到餐厅的步数期望 分析 该题是一道高斯消元+期望的题目 难点在于构造矩阵,我们发现以下结论 设某点走到餐厅的期望为Ek 1 ...

  6. codeforces E. Okabe and El Psy Kongroo(dp+矩阵快速幂)

    题目链接:http://codeforces.com/contest/821/problem/E 题意:我们现在位于(0,0)处,目标是走到(K,0)处.每一次我们都可以从(x,y)走到(x+1,y- ...

  7. Codeforces Gym10008E Harmonious Matrices(高斯消元)

    [题目链接] http://codeforces.com/gym/100008/ [题目大意] 给出 一个n*m的矩阵,要求用0和1填满,使得每个位置和周围四格相加为偶数,要求1的数目尽量多. [题解 ...

  8. Codeforces 832E Vasya and Shifts - 高斯消元

    题目传送门 快速的传送门I 快速的传送门II 题目大意 (题意比较复杂,请自行阅读原题) 可以将原题的字母都看成它们的在字符表中的下标,这样问题就变成给定$n$个$m$维向量$\vec{a_{1}}, ...

  9. POJ1487 Single-Player Games 高斯消元

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - POJ1487 题解概括 给出多个树形结构,由小写字母和数字表示,每个小写字母表示一棵小树.现在,以a为根节点 ...

随机推荐

  1. 【UE4 C++ 基础知识】<8> Delegate 委托

    概念 定义 UE4中的delegate(委托)常用于解耦不同对象之间的关联:委托的触发者不与监听者有直接关联,两者通过委托对象间接地建立联系. 监听者通过将响应函数绑定到委托上,使得委托触发时立即收到 ...

  2. Python爬虫之爬取淘女郎照片示例详解

    这篇文章主要介绍了Python爬虫之爬取淘女郎照片示例详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧 本篇目标 抓取淘宝MM ...

  3. 【做题记录】DP 杂题

    P2577 [ZJOI2004]午餐 $\texttt{solution}$ 想到贪心: 吃饭慢的先打饭节约时间, 所以先将人按吃饭时间从大到小排序. 状态: \(f[i][j]\) 表示前 \(i\ ...

  4. Spring Security:Authorization 授权(二)

    Authorization 授权 在更简单的应用程序中,身份验证可能就足够了:用户进行身份验证后,便可以访问应用程序的每个部分. 但是大多数应用程序都有权限(或角色)的概念.想象一下:有权访问你的面向 ...

  5. Logic strength modeling

    7.9 Verilog HDL提供了信号争用.双向通过门.电阻式MOS器件.动态MOS.电荷共享的精确建模,并通过允许标量净信号值具有全范围的未知值和不同强度级别或强度级别的组合来实现其他依赖于技术的 ...

  6. DDR3 IP和CIC IP仿真问题解决记录

    1.更新vivado的仿真库(data/secureip和verilog和vhdl文件夹)至最新的vivado库和生成IP的版本匹配: 2.vcs编译脚本里面把仿真库地址指向匹配的仿真库版本: 3.v ...

  7. hdu 2830 Matrix Swapping II(额,,排序?)

    题意: N*M的矩阵,每个格中不是0就是1. 可以任意交换某两列.最后得到一个新矩阵. 问可以得到的最大的子矩形面积是多少(这个子矩形必须全是1). 思路: 先统计,a[i][j]记录从第i行第j列格 ...

  8. K8S在线部署含Dashborad

    参考文章 https://www.kubernetes.org.cn/5462.html 前言 Kubernetes作为容器编排工具,简化容器管理,提升工作效率而颇受青睐.很多新手部署Kubernet ...

  9. LINUX系统新增及自动挂载硬盘-九五小庞

    Linux系统下,添加新硬盘后,自动挂载的方法   1,列出所有硬盘,找到需要挂载的硬盘,例如/dev/vdb.输入: fdisk -l   2,查看硬盘是不是已经被挂载.一个硬盘不能重复挂载,已经挂 ...

  10. Mysql教程:(三)运算符:数学运算符

    运算符:数学运算符 mysql> select class,number,maths,maths+5 from score; mysql>select class,number,chine ...