zoukankan      html  css  js  c++  java
  • [UER #6] 逃跑

    一、题目

    点此看题

    二、解法

    以前的博客不是很好,现在另起炉灶重写一波。

    首先我们知道 \(E(\overline x)=E(x^2)-E^2(x)\),这可以用期望的线性性简单推出。

    可以先预处理 \(g(t,i,j)\),表示经过 \(t\) 的时间,我们走到 \((i,j)\) 的方案数,这个可以直接 \(O(n^3)\) 递推弄出来。对于 \(E(x)\) 我们考虑求单点的贡献,设 \(f(i)\) 表示经过 \(i\) 的时间第一次到达 \((a,b)\),对于所有 \((a,b)\) 的方案数求和:

    \[f(i)=(w_1+w_2+w_3+w_4)^i-\sum_{j=0}^{i-1}f(j)\cdot g(i-j,0,0) \]

    \(pw(i)=(w_1+w_2+w_3+w_4)^i\),那么 \(E(x)\) 就可以很容易地求出了:

    \[E(x)=\sum_{i=0}^n f(i)\cdot pw(n-i) \]

    对于 \(E(x^2)\) 我们考虑求出点对之间的贡献,设 \(h(i,x,y)\) 表示在时间 \(i\) 内,我们经过 \((a,b)\),第一次到达 \((a+x,b+y)\) 的方案数。转移考虑容斥原理,总的方案数是先第一次走到 \((a,b)\),然后任意走到 \((a+x,b+y)\)

    如果去重需要减去两项:第一项是经过 \((a+x,b+y)\) 走到 \((a,b)\),然后再走到 \((a+x,b+y)\);第二项是完成目标之后还在原地打转,也就是事实上不需要这么多时间,那么总转移方程:

    \[h(i,x,y)=\sum_{j=0}^{i-1}f(j)\cdot g(i-j,x,y)-h(j,-x,-y)\cdot g(i-j,x,y)-h(j,x,y)\cdot g(i-j,0,0) \]

    因为我们是按经过顺序计算的贡献,所以如果对他求和求出来的是 \(E({x\choose 2})\),那么 \(E(x^2)\) 可以表示成:

    \[E(x^2)=E(x)+2\sum h(i,x,y)\cdot pw(n-i) \]

    三、总结

    本题的转化链十分巧妙,经过的点数可以在第一次经过的时候算贡献。而第一次经过的模型是经典问题,我们常常正难则反,减去的东西就规约到了子问题。

    状态定义也值得学习,本题是把一个等价类定义到了状态中。这是因为它们的总方案易于计算,而容斥的方式是本质相同的,最后的答案也只需要求和,所以可以压缩在一起,寻找等价类的关键就是找他们的共同点。

    #include <cstdio>
    const int M = 205;
    const int N = 105;
    const int MOD = 998244353;
    #define int long long
    int read()
    {
    	int x=0,f=1;char c;
    	while((c=getchar())<'0' || c>'9') {if(c=='-') f=-1;}
    	while(c>='0' && c<='9') {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
    	return x*f;
    }
    int n,w1,w2,w3,w4,d1,d2;
    int pw[M],f[M],g[M][M][M],h[M][M][M];
    void add(int &x,int y) {x=((x+y)%MOD+MOD)%MOD;}
    signed main()
    {
    	n=read();w1=read();
    	w2=read();w3=read();w4=read();
    	g[0][0+N][0+N]=pw[0]=1;
    	for(int i=1;i<=n;i++)
    		pw[i]=pw[i-1]*(w1+w2+w3+w4)%MOD;
    	for(int t=1;t<=n;t++)
    	for(int i=-t;i<=t;i++)
    	for(int j=-t;j<=t;j++)
    	{
    		int tmp=g[t-1][i+N][j+N];
    		add(g[t][i+1+N][j+N],tmp*w1);
    		add(g[t][i-1+N][j+N],tmp*w2);
    		add(g[t][i+N][j+1+N],tmp*w3);
    		add(g[t][i+N][j-1+N],tmp*w4);
    	}
    	for(int i=0;i<=n;i++)
    	{
    		f[i]=pw[i];
    		for(int j=0;j<i;j++)
    			add(f[i],-f[j]*g[i-j][0+N][0+N]);
    		add(d1,f[i]*pw[n-i]);
    	}
    	for(int i=1;i<=n;i++)
    	for(int x=-i;x<=i;x++)
    	for(int y=-i;y<=i;y++)
    	{
    		if(x==0 && y==0) continue;
    		int &r=h[i][x+N][y+N];
    		for(int j=0;j<i;j++)
    		{
    			add(r,f[j]*g[i-j][x+N][y+N]);
    			add(r,-h[j][-x+N][-y+N]*g[i-j][x+N][y+N]);
    			add(r,-h[j][x+N][y+N]*g[i-j][0+N][0+N]);
    		}
    		add(d2,r*pw[n-i]);
    	}
    	add(d2,d2);add(d2,d1);
    	printf("%lld\n",((d2*pw[n]-d1*d1)%MOD+MOD)%MOD);
    }
    
  • 相关阅读:
    docker 容器启动时设置环境变量source
    解决docker容器中Centos7系统的中文乱码
    Python 常用的标准库以及第三方库有哪些?
    excel 两列值匹配取另外一列值 INDEX MATCH 函数
    Dockerfile编写,以及设置一个自启动脚本
    主机、Docker时间与时区设置总结
    CentOS安装scp命令
    Python3中遇到UnicodeEncodeError: 'ascii' codec can't encode characters in ordinal not in range(128)
    yum 安装 tomcat
    Docker退出容器不关闭容器的方法
  • 原文地址:https://www.cnblogs.com/C202044zxy/p/15570479.html
Copyright © 2011-2022 走看看