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;
}