1 条题解

  • 0
    @ 2025-8-24 22:24:27

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar tommymio
    Cruel world

    搬运于2025-08-24 22:24:27,当前版本为作者最后更新于2020-09-29 10:22:33,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    期望入门题。

    这题非常的好,考察了期望的线性性质和选手的推柿子能力,给良心出题人点赞(然而我月赛时并没有做出来

    注:期望的线性性质:在本题中体现为从 xx 点到 yy 点的期望步数 $E_{x\to y}=E_{x\to x+1}+...+E_{y-1 \to y}=\sum\limits_{i=x}^{y-1}E_{i\to i+1}$。

    对于这类在图上随机游走的问题,我们一般会设 Exx+1E_{x\to x+1} 表示从 xx 点到 x+1x+1 点的期望步数,那么答案就是 x=0nExx+1\sum\limits_{x=0}^n E_{x\to x+1} 的值。

    不妨先根据期望的定义列出 Exx+1E_{x\to x+1} 的转移式(其中 duxdu_x 表示 xx返祖边的条数,而 EE 表示 xx返祖边的边集):

    $$E_{x\to x+1}=\frac{1}{du_x+1}\times1+\frac{1}{du_x+1}\sum_{(x,y)\in E} (E_{y\to x+1}+1) $$

    Eyx+1=i=yxEii+1E_{y\to x+1}=\sum\limits_{i=y}^{x}E_{i\to i+1} 代入上式并对上式进行化简:

    $$E_{x\to x+1}=1+\frac{1}{du_x+1}\sum_{(x,y)\in E}\sum_{i=y}^xE_{i\to i+1} $$

    此时记 Exx+1E_{x\to x+1}fxf_x,记 sumx=i=0xfisum_x=\sum\limits_{i=0}^x f_i,则上式可写作:

    $$f_x=1+\frac{1}{du_x+1}\sum_{(x,y)\in E}sum_x-sum_{y-1} $$

    发现等式两边都含有 Exx+1E_{x\to x+1} ,把 Exx+1E_{x\to x+1} 全部提到左边(为了让 fxf_x 能够转移),并消去和式系数 1dux+1\frac{1}{du_x+1},得:

    fx=(dux+1)+(x,y)Esumx1sumy1f_x=(du_x+1)+\sum_{(x,y)\in E}sum_{x-1}-sum_{y-1}

    到这里维护一下前缀和,就可以直接转移了。总时间复杂度为 O(n)O(n)

    上式的化简步骤都是一些常见的状态转移方程的 Dirty Work\text{Dirty Work},本来不想写出来的(

    Show the Code

    #include<cstdio>
    #define int ll
    typedef long long ll;
    const int mod=998244353;
    int cnt=0;
    int h[1000005],to[2000005],ver[2000005];
    int f[1000005],sum[1000005],du[1000005];
    inline int read() {
    	register int x=0,f=1;register char s=getchar();
    	while(s>'9'||s<'0') {if(s=='-') f=-1;s=getchar();}
    	while(s>='0'&&s<='9') {x=x*10+s-'0';s=getchar();}
    	return x*f;
    }
    inline void add(int x,int y) {to[++cnt]=y;ver[cnt]=h[x];h[x]=cnt;}
    signed main() {
    	int id=read(),n=read(),m=read();
    	for(register int i=1;i<=m;++i) {int x=read(),y=read();add(x,y);++du[x];}
    	for(register int x=1;x<=n;++x) {
    		f[x]=du[x]+1;
    		for(register int i=h[x];i;i=ver[i]) {
    			int y=to[i];
    			f[x]=((f[x]+(sum[x-1]-sum[y-1])%mod)%mod+mod);
    		}
    		sum[x]=(sum[x-1]+f[x])%mod;
    	}
    	printf("%lld\n",sum[n]); 
    	return 0;
    }
    
    • 1

    信息

    ID
    4422
    时间
    1000ms
    内存
    128MiB
    难度
    5
    标签
    递交数
    0
    已通过
    0
    上传者