E. Expected Value
E. Expected Value.
题意:
给出 n ≤ 3000 n \le 3000 n≤3000的 稀疏无向图(边的个数是O(n)的),求从1号点出发随机游走到第1次到达n号点的期望步数。
题解:
直接上矩阵肯定是不行的。
贴个快速消元的模板。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 100100;
const long long mod = 998244353;
long long pow_mod(long long a, long long n, long long p) {
long long ans = 1;
while (n) {
if (n & 1)
ans = ans * a % p;
a = a * a % p;
n >>= 1;
}
return ans;
}
long long inv(long long a) {
return pow_mod(a, mod - 2, mod);
}
struct fast_gauss_mod {
static const int maxstate = 3000000;
static const int table_size = 5110007;
struct {
long long val;
int r, c, next, right, down;
} node[maxstate];
int first[table_size], row[maxn], column[maxn], vis[maxn], length[maxn], sz, n;
void init(int n) { //待消元的矩阵大小是n * (n + 1)的
this->n = n;
sz = 0;
memset(first, 0, sizeof(first));
memset(row, 0, sizeof(row));
memset(column, 0, sizeof(column));
memset(vis, 0, sizeof(vis));
memset(length, 0, sizeof(length));
}
long long& A(int r, int c) {
const int h = ((long long)r << 20 | c) % table_size;
for (int i = first[h]; i; i = node[i].next)
if (node[i].r == r && node[i].c == c)
return node[i].val;
int i = ++sz;
node[i].next = first[h];
first[h] = i;
node[i].right = row[r];
row[r] = i;
node[i].down = column[c];
column[c] = i;
node[i].r = r;
node[i].c = c;
node[i].val = 0;
length[r] += 1;
return node[i].val;
}
void insert(int r, int c, long long v) { //在矩阵的第r行第c列填上v
A(r, c) = v;
}
vector<long long> solve() { //无解或用无穷解时返回空vector
vector<long long> ans(n);
for (int i = 0; i < n; ++i) {
int r = -1;
for (int x = column[i]; x; x = node[x].down) {
int j = node[x].r;
if (!vis[j] && node[x].val != 0)
if (r < 0 || length[j] < length[r])
r = j;
}
if (r == -1)
return {};
int* last = &row[r];
for (int y = row[r]; y; y = node[y].right) {
if (node[y].val == 0)
*last = node[y].right;
else
last = &node[y].right;
}
auto pivot = mod - inv(A(r, i));
for (int x = column[i]; x; x = node[x].down) {
int j = node[x].r;
if (!vis[j] && j != r) {
auto ratio = node[x].val * pivot % mod;
for (int y = row[r]; y; y = node[y].right) {
int k = node[y].c;
A(j, k) = (A(j, k) + ratio * node[y].val) % mod;
}
length[j] -= 1;
}
}
ans[i] = r;
vis[r] = true;
}
for (int i = n - 1; i >= 0; --i) {
int r = ans[i];
auto pivot = (mod - A(r, n)) * inv(A(r, i)) % mod;
for (int x = column[i]; x; x = node[x].down) {
int j = node[x].r;
if (j != r)
A(j, n) = (A(j, n) + node[x].val * pivot) % mod;
}
}
for (int i = 0; i < n; ++i)
ans[i] = A(ans[i], n) * inv(A(ans[i], i)) % mod;
return ans;
}
}gauss;
vector<int> g[4000];
int main() {
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
int n; cin >> n;
for (int i = 0; i < n;i++) {
int x, y; cin >> x >> y;
}
int m; cin >> m;
for (int i = 0; i < m;i++) {
int u, v; cin >> u >> v;
u--, v--;
g[u].push_back(v);
g[v].push_back(u);
}
gauss.init(n);
for (int i = 0; i < n - 1;i++)if (g[i].size()) {
gauss.insert(i, i, 1);
int deg = g[i].size();
deg = mod - inv(deg);
for (int v : g[i])gauss.insert(i, v, deg);
gauss.insert(i, n, 1);
}
gauss.insert(n - 1, n - 1, 1);
vector<long long > res = gauss.solve();
cout << res[0] << "\n";
}