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. 性能利器 Takin 来了!首个生产环境全链路压测平台正式开源

    6 月 25 日,国内知名的系统高可用专家数列科技宣布开源旗下核心产品能力,对外开放生产全链路压测平台产品的源代码,并正式命名为 Takin. 目前中国人寿.顺丰科技.希音.中通快递.中国移动.永辉超 ...

  2. Java:ConcurrentHashMap类小记-1(概述)

    Java:ConcurrentHashMap类小记-1(概述) 对 Java 中的 ConcurrentHashMap类,做一个微不足道的小小小小记,分三篇博客: Java:ConcurrentHas ...

  3. Java:泛型小记

    Java:泛型小记 对 Java 中的 泛型类,做一个微不足道的小小小小记 泛型实现 概述 开篇: List<String> l1 = new ArrayList<String> ...

  4. 移动端 h5 uniapp 读,写,删本地文件或sd文件

    移动端 h5 uniapp 读,写,删本地文件或sd文件 应用场景: 当我们需要做离线应用或者是加载本地文件时使用到此方法.(本篇文章给大家分享访问app私有文件目录,系统公共目录,sd外置存储的文件 ...

  5. 【技术博客】Flutter—使用网络请求的页面搭建流程、State生命周期、一些组件的应用

    Flutter-使用网络请求的页面搭建流程.State生命周期.一些组件的应用 使用网络请求的页面搭建流程 ​ 在开发APP时,我们常常会遇到如下场景:进入一个页面后,要先进行网络调用,然后使用调用返 ...

  6. 【二食堂】Alpha - Scrum Meeting 3

    Scrum Meeting 3 例会时间:4.13 12:00 - 12:30 进度情况 组员 昨日进度 今日任务 李健 1. 继续学习前端知识,寻找一些可用的框架.issue 1. 搭建主页html ...

  7. matlab添加永久路径

    addpath('D:\MATLAB6p5\toolbox\svm'); 临时添加路径,不能添加子目录 addpath(genpath('D:\MATLAB6p5\toolbox\svm'));临时添 ...

  8. 利用Microsoft Graph开发微软的Exchange Calendar会议、Team

    Microsoft Graph是什么? Microsoft Graph 是 Microsoft 365 中通往数据和智能的网关. 它提供统一的可编程模型,可用于访问 Microsoft 365.Win ...

  9. 2021 CCPC女生赛

    newbie,A了五题铜牌收工 比赛时和队友悠哉游哉做题,想着干饭,最后幸好没滚出铜尾. 贴一下比赛过的代码 A题 签到 队友A的,判断正反方向序列是否符合要求 /*** * @Author: _Kr ...

  10. Python 字符串的encode与decode

    python的str,unicode对象的encode和decode方法 python中的str对象其实就是"8-bit string" ,字节字符串,本质上类似java中的byt ...