P6835
[Cnoi2020]线形生物
期望 DP。
因为可以在图上随机游走,直接以点为状态转移有些困难。
定义
然后我们定义
然后就有转移:
然后我们根据
显然我们可以前缀和化简。定义
然后我们把
移项,再把左边的系数化为 1,就能得到:
这时我们发现,递推所需要的期望只有相邻两个点之间的期望了,所以我们干脆定义
于是就得到了一个很线性的转移方程:
然后就可以线性递推了。
最后答案就是:
时间复杂度
最后注意取模中有减法,所以要加上模数。
代码:
#include<iostream>
#include<cstdio>
#define ll long long
using namespace std;
const ll N=1e6,mo=998244353;
ll n,m,id,u,v,tot;
ll cnt_ae[N+5],ver[N+5],nxt[N+5],head[N+5],f[N+5],c[N+5];
void add(ll u,ll v) {
ver[++tot]=v;nxt[tot]=head[u];head[u]=tot;
}
inline ll read() {
ll ret=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9') {if(ch=='-') f=-f;ch=getchar();}
while(ch>='0'&&ch<='9') {ret=(ret<<3)+(ret<<1)+ch-'0';ch=getchar();}
return ret*f;
}
void write(ll x) {
static char buf[22];static ll len=-1;
if(x>=0) {
do{buf[++len]=x%10+48;x/=10;}while(x);
}
else {
putchar('-');
do{buf[++len]=-(x%10)+48;x/=10;}while(x);
}
while(len>=0) putchar(buf[len--]);
}
int main() {
id=read();n=read();m=read();
for(ll i=1;i<=m;i++) {
u=read();v=read();
add(u,v);cnt_ae[u]++;
}
for(ll i=1;i<=n;i++) {
f[i]=(cnt_ae[i]+1)%mo;
for(ll j=head[i];j;j=nxt[j]) {
f[i]=(f[i]+(c[i-1]-c[ver[j]-1])%mo+mo)%mo;
}
c[i]=(c[i-1]+f[i])%mo;
}
write(c[n]);
return 0;
}