Loading

P6154 游走 简单期望

2 P6154 游走 简单期望

链接

不难发现,所有的路径被选概率都是一样的,也就是说,所有的路径被选的概率是 \(1\) 除以路径的总条数。再者我们需要算出所有路径的长度总和。

考虑 dp 。令 \(f_k\) 表示结尾为 \(k\) 的路径长度总和,\(g_k\) 表示结尾为 \(k\) 的路径条数。

不难设计一个 dp :

\[f_u\sum\limits_{v,(v,u)\in E} f_v+g_v\\ g_u=\sum\limits_{v,(v,u)\in E}g_v \]

累加所有答案算逆元就可以了。

代码:

#include<bits/stdc++.h>
#define dd double
#define ld long double
#define ll long long
#define int long long
#define uint unsigned int
#define ull unsigned long long
#define N 100010
#define M 700010
using namespace std;

const int INF=0x3f3f3f3f;
const ll mod=998244353;

template<typename T> inline void read(T &x) {
    x=0; int f=1;
    char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c == '-') f=-f;
    for(;isdigit(c);c=getchar()) x=x*10+c-'0';
    x*=f;
}

int rd[N],n,m;

struct edge{
    int to,next;
    inline void intt(int to_,int ne_){
        to=to_;next=ne_;
    }
};
edge li[M];
int head[N],tail;

inline void add(int from,int to){
    li[++tail].intt(to,head[from]);
    head[from]=tail;
}

queue<int> q;

ll ans1,ans2,f[N],g[N];
bool vis[N];

inline void solve(){
    while(q.size()){
        int top=q.front();q.pop();g[top]++;ans1+=f[top];ans2+=g[top];
        ans1%=mod;ans2%=mod;
        for(int x=head[top];x;x=li[x].next){
            int to=li[x].to;
            f[to]+=f[top]+g[top];g[to]+=g[top];
            f[to]%=mod;g[to]%=mod;
            rd[to]--;
            if(!rd[to]) q.push(to);
        }
    }
}

inline ll ksm(ll a,ll b,ll mod){
    a%=mod;
    ll res=1;
    while(b){
        if(b&1) (res*=a)%=mod;
        a=a*a%mod;
        b>>=1;
    }
    return res;
}

signed main(){
    read(n);read(m);
    for(int i=1;i<=m;i++){
        int from,to;read(from);read(to);
        add(from,to);rd[to]++;
    }
    for(int i=1;i<=n;i++){
        if(!rd[i]) q.push(i);
    }
    solve();
    // printf("%lld %lld\n",ans1,ans2);
    ll inv=ksm(ans2,mod-2,mod);
    printf("%lld\n",ans1*inv%mod);
    return 0;
}
posted @ 2021-07-08 14:13  hyl天梦  阅读(47)  评论(0编辑  收藏  举报