傳送門
這題真惋惜,比賽的時候最後10分鐘推出來了,可是10分鐘寫不完高斯消元啊。
這題思路還挺多,有題解的一種,還有咱們隊裏大佬的另外一種,以及我本身的一種。可是其餘兩個思路我都不是很懂,遂只能將本身的思路記錄於此了。php
這題我就是按照圖上的隨機遊走模型去作的。ios
咱們先把起點選擇在\(1\)號點。令\(E(u)\)表示走到\(u\),且能繼續走下去的機率,\(f(u)\)表示走到\(u\),且停在\(u\)的機率。能繼續走下去就意味着上一時刻不能在\(u\),停住就意味着上一時刻必須在\(u\).c++
那麼能夠列出關係式:git
\(F(u)=E(u) * P(u,u) + P(1,1)*(u == 1)\),
\(E(u)=\sum\limits_{v = 1,v \neq u} ^ {n} E(v) * P(v, u) + P(1,u) * (u \neq 1)\).ide
注意後面的常數項,由於剛開始在\(1\)號點,因此有\(P(1,1)\)的機率停住,有\(P(1,u)\)的機率走到別的點。(就由於這些常數項我沒整明白,推不對又放棄了)
\(E(u)\)之間的關係能夠用高斯消元來解,代入就能求得\(F(u)\)了。
上面是起點在\(1\)的狀況,那麼對於起點在\(x\)的狀況,咱們發現係數矩陣是同樣的,只有增廣矩陣的最右邊一列是不同的,所以能夠將增廣矩陣寫成\(n+n\)列,\(n\)個方程組同時解。那麼時間複雜度就是\(O(n * n * 2n)\).ui
固然,也能夠把矩陣方程列出來而後求逆,效果同樣。spa
#include<cstdio> #include<iostream> #include<cmath> #include<algorithm> #include<cstring> #include<cstdlib> #include<cctype> #include<vector> #include<queue> #include<assert.h> #include<ctime> using namespace std; #define enter puts("") #define space putchar(' ') #define Mem(a, x) memset(a, x, sizeof(a)) #define In inline #define forE(i, x, y) for(int i = head[x], y; ~i && (y = e[i].to); i = e[i].nxt) typedef long long ll; typedef double db; const int INF = 0x3f3f3f3f; const db eps = 1e-8; const ll mod = 998244353; const int maxn = 302; In ll read() { ll ans = 0; char ch = getchar(), las = ' '; while(!isdigit(ch)) las = ch, ch = getchar(); while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar(); if(las == '-') ans = -ans; return ans; } In void write(ll x) { if(x < 0) x = -x, putchar('-'); if(x >= 10) write(x / 10); putchar(x % 10 + '0'); } In ll ADD(ll a, ll b) {return a + b < mod ? a + b : a + b - mod;} In ll quickpow(ll a, ll b) { ll ret = 1; for(; b; b >>= 1, a = a * a % mod) if(b & 1) ret = ret * a % mod; return ret; } int n, m; ll p[maxn][maxn]; ll f[maxn][maxn << 1]; In void Gauss() { for(int i = 1; i <= n; ++i) { int pos = i; while(pos <= n && !f[pos][i]) ++pos; if(pos > n) continue; if(pos > i) swap(f[i], f[pos]); ll inv = quickpow(f[i][i], mod - 2); for(int j = i; j <= m; ++j) f[i][j] = f[i][j] * inv % mod; for(int j = i + 1; j <= n; ++j) { ll tp = f[j][i]; for(int k = i; k <= m; ++k) f[j][k] = ADD(f[j][k], mod - tp * f[i][k] % mod); } } for(int i = n; i; --i) for(int j = i - 1; j; --j) for(int k = n + 1; k <= m; ++k) f[j][k] = ADD(f[j][k], mod - f[j][i] * f[i][k] % mod); } In void solve() { Mem(f, 0); m = n + n; for(int i = 1; i <= n; ++i) { ll sum = 0; for(int j = 1; j <= n; ++j) sum += p[i][j]; sum = quickpow(sum, mod - 2); for(int j = 1; j <= n; ++j) p[i][j] = p[i][j] * sum % mod; } for(int i = 1; i <= n; ++i) { f[i][i] = 1; for(int j = 1; j <= n; ++j) if(i ^ j) { f[i][j] = mod - p[j][i]; f[j][n + i] = ADD(f[j][n + i], p[i][j]); } } Gauss(); for(int i = 1; i <= n; ++i) for(int j = 1; j <= n; ++j) { write(ADD(f[j][n + i] * p[j][j] % mod, (i == j) * p[j][j])); j == n ? enter : space; } } int main() { int T = read(); while(T--) { n = read(); for(int i = 1; i <= n; ++i) for(int j = 1; j <= n; ++j) p[i][j] = read(); solve(); } return 0; }