[UER#6 C]逃跑

版权声明:本文是蒟蒻写出来的,神犇转载也要说一声哦! https://blog.csdn.net/WerKeyTom_FTD/article/details/80432137

做法

要求的是方差,实际就是求所有情况下经过不同位置的个数和以及经过不同位置的平方和,设为dd2
一共有四种方向向量,任意走法对应一种向量序列。
先预处理W(i,x,y)表示长度为i,和为(x,y)的向量序列有多少种。
如何求d,当然是很简单的。
每个坐标显然可以独立统计贡献,我们希望在每个坐标第一次被走到时统计到它。
我们设g[i]表示长度为i,且不存在1ji满足前j个向量前缀和为(0,0)
以后这种类似的情况简单称为“不存在前缀(0,0)”。
显然可以容斥:
g[i]=(w1+w2+w3+w4)ij=1iW(j,0,0)g[ij]
那么就有
d=i=0n(x,y)W(i,x,y)g[ni]
在时刻i我们走到了(x,y),之后再也没有再走到过。
为了简单计算,我们更改d2的含义,对于一种情况,对于两个不同的位置(有序)如果都到达过,给d2贡献1。那么原本的d2等于新的d22加上d
类似的我们设出R(i,x,y)表示长度为i,和为(x,y),不存在前缀(0,0)
R的计算也可以容斥:
R(i,x,y)=W(i,x,y)j=1iW(j,0,0)R(ij,x,y)
然后我们设S(i,x,y)表示长度为i,和为(0,0),且存在前缀(x,y)
那么显然
S(i,x,y)=j=1iW(j,x,y)R(ij,x,y)
有了这几个作辅助,我们可以设F(i,x,y)表示长度为i的所有情况,前j个向量的和(a,b)为第一次到达,然后接下来ij个向量的和为(x,y),且在位置i时,(a+x,b+y)第一次到达,这样的两个不同位置总数(因此xy不为0)。
可能有点绕。
考虑怎么得到它呢?
F(i,x,y)+=j=1ig[j]W(ij,x,y)
这个是(a,b)是第一次到达的总方案数。
考虑不合法的情况,即(a,b)到达(a+x,b+y)后,这个(a+x,b+y)已经不是第一次到达了,它可能在第一次到达(a,b)前第一次到达,也可能在第一次到达(a,b)后第一次到达。
F(i,x,y)=j=1ig[j]S(ij,x,y)
如果在第一次到达(a,b)之前就到达了(a+x,b+y),考虑去掉这种方案,那么相当于第一次到达(a+x,b+y)后又走了回来,而且这途中要经过(a,b)。这样一定包含了所有第一次到达(a,b)之前就到达了(a+x,b+y)的方案,但是并不止。我们中途去遍历了(a,b),但是并不一定中途遍历时这个(a,b)才第一次经过。因此我们还会减掉第一次到达(a,b)后,再第一次到达(a+x,b+y),最后在时刻i重新回到(a+x,b+y),这中途还重新回过(a,b)
F(i,x,y)=j=1iF(j,x,y)(W(ij,0,0)S(ij,x,y))
我们考虑第一次到达(a+x,b+y)是在第一次到达(a,b)后的不合法方案,注意到上一条式子里我们减掉了第一次到达(a+x,b+y)到时刻i间重新回过(a,b)的方案,这里为了不减重要减掉这种方案(即S(ij,x,y))。
那么在得到了F之后,我们很简单就能统计d2
d2=i=0n(a,b)(x,y)F(i,a,b)W(ni,x,y)
至此,本题解决。时间复杂度O(n4)

#include<cstdio>
#include<algorithm>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fd(i,a,b) for(i=a;i>=b;i--)
using namespace std;
typedef long long ll;
const int maxn=220+10,mo=998244353;
int w[5],dx[5]={0,0,0,1,-1},dy[5]={0,-1,1,0,0};
int p1[maxn][maxn][maxn],p2[maxn][maxn][maxn],p3[maxn][maxn][maxn],p4[maxn][maxn][maxn];
int g[maxn];
int i,j,k,l,r,s,t,n,m,x,y,ans,all,d,d2;
int &W(int n,int x,int y){ return p1[x+105][y+105][n]; }
int &F(int n,int x,int y){ return p2[x+105][y+105][n]; }
int &S(int n,int x,int y){ return p3[x+105][y+105][n]; }
int &R(int n,int x,int y){ return p4[x+105][y+105][n]; }
int abs(int x){
    return x<0?-x:x;
}
int main(){
    scanf("%d",&n);
    fo(i,1,4) scanf("%d",&w[i]);
    W(0,0,0)=1;
    fo(i,1,n)
        fo(x,-n,n)
            fo(y,-n,n)
                if (abs(x)+abs(y)<=i)
                    fo(k,1,4)
                        (W(i,x,y)+=(ll)w[k]*W(i-1,x+dx[k],y+dy[k])%mo)%=mo;
    g[0]=1;
    all=w[1]+w[2]+w[3]+w[4];
    t=1;
    fo(i,1,n){
        t=(ll)t*all%mo;
        g[i]=t;
        fo(j,1,i) (g[i]-=(ll)W(j,0,0)*g[i-j]%mo)%=mo;
    }
    fo(i,1,n)
        fo(x,-n,n)
            fo(y,-n,n)
                if (abs(x)+abs(y)<=i){
                    R(i,x,y)=W(i,x,y);
                    fo(j,1,i-abs(x)-abs(y))
                        (R(i,x,y)-=(ll)W(j,0,0)*R(i-j,x,y)%mo)%=mo;
                }
    fo(i,1,n)
        fo(x,-n,n)
            fo(y,-n,n)
                if (abs(x)+abs(y)<=i){
                    fo(j,max(abs(x)+abs(y),1),i-abs(x)-abs(y))
                        (S(i,x,y)+=(ll)W(j,x,y)*R(i-j,-x,-y)%mo)%=mo;
                }
    fo(i,1,n)
        fo(x,-n,n)
            fo(y,-n,n)
                if (abs(x)+abs(y)<=i){
                    if (!x&&!y) continue;
                    fo(j,max(abs(x)+abs(y),1),i)
                        (F(i,x,y)+=(ll)(W(j,x,y)-S(j,x,y))*g[i-j]%mo)%=mo;
                    fo(j,1,i)
                        (F(i,x,y)-=(ll)(W(j,0,0)-S(j,x,y))*F(i-j,x,y)%mo)%=mo;
                }
    fo(i,0,n)
        fo(x,-n,n)
            fo(y,-n,n)
                if (abs(x)+abs(y)<=i) (d+=(ll)W(i,x,y)*g[n-i]%mo)%=mo;
    fo(i,0,n){
        t=0;
        fo(x,-n,n)
            fo(y,-n,n)
                if ((x||y)&&abs(x)+abs(y)<=n-i) (t+=F(n-i,x,y))%=mo;
        fo(x,-n,n)
            fo(y,-n,n)
                if (abs(x)+abs(y)<=i) (d2+=(ll)t*W(i,x,y)%mo)%=mo;
    }
    d2=((ll)d2*2%mo+d)%mo;
    t=1;
    fo(i,1,n) t=(ll)t*all%mo;
    ans=((ll)d2*t%mo-(ll)d*d%mo)%mo;
    (ans+=mo)%=mo;
    printf("%d\n",ans);
}
阅读更多

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