UOJ#211. 【UER #6】逃跑

版权声明:...............转载说一声并注明出处qaq............... https://blog.csdn.net/L_0_Forever_LF/article/details/80724892

谢谢栋栋教我这题qaq

因为完全按照他的方法做的所以题解和他的可能会长得很像qaq


先画一下柿子
ans=E×all=all(aiave)2=all(ai22ai×ave+ave2)
ave=aiall

ans=allai2(ai)2

我们设w=w1+w2+w3+w4d=aid2=ai2
ans=all×d2d2,其中all=wn,考虑怎么求d,d2


我们将四个方向看作四个向量,一开始在(0,0),走到(x,y)相当于向量和为(x,y)
以下将 “ 不存在一个j(j>0)满足前j个向量和为(x,y) ” 简称为不存在前缀(x,y),后缀同理

W[i][x][y]表示走了i步,走到(x,y)的方案数
g[i]表示走了i步,不存在前缀(0,0)的方案数(同时也是不存在后缀(0,0)的方案数)
g[i]=wijW[j][0][0]×g[ij]

那么d就很容易计算了,我们分开考虑每个格子的贡献,有
d=ig[i]×wni

对于d2,我们考虑像管道取珠那样转化平方贡献的方法计算他

R[i][x][y]表示走了i步,和为(x,y),不存在前缀(0,0)
R[i][x][y]=W[i][x][y]jW[j][0][0]×R[ij][x][y]

S[i][x][y]表示走了i步,和为(0,0),存在前缀(x,y)
S[i][x][y]=jW[j][x][y]×R[ij][x][y]

F[i][x][y]表示
对于所有长度为i的向量序列,其前j(j<i)个向量和为(a,b),后ij个向量和为(x,y)
且第j步第一次到达(a,b)(不存在后缀(0,0)),第i步第一次到达(a+x,b+y)
这样的j的个数之和

其实就是将一条路径覆盖的ai个格子,按照第一次到达的顺序排序后,从左到右取出每个格子和后面的所有格子匹配贡献到ai2里,最后要乘2算上倒序的匹配,再加上ai表示自己和自己匹配

F[i][x][y]的dp式分三部分

F[i][x][y]+=jg[j]×W[ij][x][y]
因为g[j]也能表示不存在后缀(0,0)即第一次到达某个点(a,b),然后剩下ij步和为(x,y),所有合法方案他一定能算进去,考虑他会算到哪些不合法的方案
会算到不合法主要是因为我们不能保证第i步时第一次到达(a+x,b+y),他可能在第j步前就到达过,或者在第j步后第i步前到达过

F[i][x][y]=jg[j]×S[ij][x][y]
这里减去的是第j步前到达(a+x,b+y)后走回(a,b)再回到(a+x,b+y)的方案,但他还会减去第一次到(a,b)后到(a+x,b+y)再绕回(a,b)最后又回到(a+x,b+y)的方案,因为我们第一部分并不会算入这种情况,我们要在第三部分把这些方案加回来

F[i][x][y]=jF[j][x][y]×(W[ij][0][0]S[ij][x][y])
这里的S[ij][x][y]就是我们在第二部分多减的东西

然后d2=(i,x,yF[i][x][y]×wni)×2+d

然后这题就做完啦(撒花)

code:

#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<complex>
#include<iostream>
#include<algorithm>
#define ll long long
#define W(i,x,y) W[x+base][y+base][i]
#define R(i,x,y) R[x+base][y+base][i]
#define S(i,x,y) S[x+base][y+base][i]
#define F(i,x,y) F[x+base][y+base][i]
using namespace std;

const int maxn = 210;
const int mod = 998244353;
const int dx[]={-1,0,1,0};
const int dy[]={0,1,0,-1};
const int base = 105;
inline void add(int &a,const int &b){a+=b;if(a>=mod)a-=mod;}
inline void dec(int &a,const int &b){a-=b;if(a<0)a+=mod;}

int n,w[4],pw[maxn];
int W[maxn][maxn][maxn],g[maxn],R[maxn][maxn][maxn],S[maxn][maxn][maxn],F[maxn][maxn][maxn];

int main()
{
    //freopen("tmp.in","r",stdin);
    //freopen("tmp.out","w",stdout);

    scanf("%d",&n);
    scanf("%d%d%d%d",&w[0],&w[2],&w[1],&w[3]);
    pw[0]=1,pw[1]=w[0]+w[1]+w[2]+w[3]; for(int i=2;i<=n;i++) pw[i]=(ll)pw[i-1]*pw[1]%mod;

    W(0,0,0)=1;
    for(int i=1;i<=n;i++)
    {
        for(int x=-i;x<=i;x++) for(int y=-i+abs(x);y<=i-abs(x);y++)
            for(int k=0;k<4;k++) add(W(i,x,y),(ll)W(i-1,x+dx[k],y+dy[k])*w[(k+2)&3]%mod);
    }
    for(int i=0;i<=n;i++)
    {
        g[i]=pw[i];
        for(int j=1;j<=i;j++) dec(g[i],(ll)W(j,0,0)*g[i-j]%mod);
    }
    for(int i=0;i<=n;i++)
    {
        for(int x=-i;x<=i;x++) for(int y=-i+abs(x);y<=i-abs(x);y++)
        {
            R(i,x,y)=W(i,x,y);
            for(int j=1;j<i;j++) dec(R(i,x,y),(ll)W(j,0,0)*R(i-j,x,y)%mod);
        }
    }
    for(int i=0;i<=n;i++)
    {
        for(int x=-i;x<=i;x++) for(int y=-i+abs(x);y<=i-abs(x);y++)
        {
            for(int j=1;j<i;j++) add(S(i,x,y),(ll)W(j,x,y)*R(i-j,-x,-y)%mod);
        }
    }
    for(int i=1;i<=n;i++)
    {
        for(int x=-i;x<=i;x++) for(int y=-i+abs(x);y<=i-abs(x);y++)
        {
            for(int j=0;j<i;j++) add(F(i,x,y),(ll)g[j]*W(i-j,x,y)%mod);
            for(int j=0;j<i;j++) dec(F(i,x,y),(ll)g[j]*S(i-j,-x,-y)%mod);
            for(int j=0;j<i;j++) dec(F(i,x,y),(ll)F(j,x,y)*((W(i-j,0,0)-S(i-j,-x,-y)+mod)%mod)%mod);
        }
    }
    int d=0,d2=0;
    for(int i=0;i<=n;i++) add(d,(ll)g[i]*pw[n-i]%mod);
    for(int i=0;i<=n;i++)
    {
        for(int x=-i;x<=i;x++) for(int y=-i+abs(x);y<=i-abs(x);y++) if(x||y)
            add(d2,(ll)F(i,x,y)*pw[n-i]%mod);
    }
    add(d2,d2);
    add(d2,d);
    int ans=(ll)d2*pw[n]%mod; dec(ans,(ll)d*d%mod);
    printf("%d\n",ans);

    return 0;
}
阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页