300iq Contest 1 E. Expected Value

E. Expected Value


E. Expected Value.
题意:
给出 n ≤ 3000 n \le 3000 n3000稀疏无向图(边的个数是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";
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值