UOJ#211. 【UER #6】逃跑

谢谢栋栋教我这题qaq

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


先画一下柿子
a n s = E × a l l = a l l ( a i a v e ) 2 = a l l ( a i 2 2 a i × a v e + a v e 2 )
a v e = a i a l l

a n s = a l l a i 2 ( a i ) 2

我们设 w = w 1 + w 2 + w 3 + w 4 d = a i d 2 = a i 2
a n s = a l l × d 2 d 2 ,其中 a l l = w n ,考虑怎么求 d , d 2


我们将四个方向看作四个向量,一开始在(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 ] = w i j W [ j ] [ 0 ] [ 0 ] × g [ i j ]

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

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

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

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

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

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

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

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

F [ i ] [ x ] [ y ] = j g [ j ] × S [ i j ] [ 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 ] = j F [ j ] [ x ] [ y ] × ( W [ i j ] [ 0 ] [ 0 ] S [ i j ] [ x ] [ y ] )
这里的 S [ i j ] [ x ] [ y ] 就是我们在第二部分多减的东西

然后 d 2 = ( i , x , y F [ i ] [ x ] [ y ] × w n i ) × 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;
}

猜你喜欢

转载自blog.csdn.net/L_0_Forever_LF/article/details/80724892