Live2D

【UER #6】逃跑

题目传送门

Solution

首先我们可以看出求方差的期望其实就是求 \(E(x^2)-E(x)^2\)

首先考虑怎么求 \(E(x)\)。我们可以发现其实可以对于每一个数去算包含它的路径数,所以我们可以设 \(g(t,x,y)\) 表示 \(t\) 时刻到 \((x,y)\) 的方案数,然后我们可以设 \(f(i)\) 表示时刻 \(i\) 第一次走到的 \((x,y)\) 的方案数之和,于是我们可以得到转移式:

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

考虑如何求 \(E(x^2)\)。可以发现的是,\(E(x^2)=2E(\binom{x}{2})+E(x)\),而 \(E(\binom{x}{2})\) 存在组合意义,表示在路径中选两个数出来的方案数。

所以我们可以考虑设 \(h(t,x,y)\) 表示之前到了 \((a,b)\) 然后 \(t\) 时刻到了 \((a+x,b+y)\) 的方案数之和,存在转移式:

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

减的第一个表示先出现 \((a+x,b+y)\) 再到 \((a,b)\) 再到 \((a+x,b+y)\) 的方案数,后面那个数就是去掉 \((a+x,b+y)\) 不是第一个出现的方案数。

然后这个题就可以 \(\Theta(n^4)\) 解决了,似乎用分治 NTT 可以做到 \(\Theta(n^3\log n)\) ?。

Code

#include <bits/stdc++.h>
using namespace std;

#define Int register int
#define mod 998244353
#define MAXN 105

template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;}
template <typename T,typename ... Args> inline void read (T &t,Args&... args){read (t);read (args...);}
template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');}
template <typename T> inline void chkmax (T &a,T b){a = max (a,b);}
template <typename T> inline void chkmin (T &a,T b){a = min (a,b);}

int n,w1,w2,w3,w4,g[MAXN][MAXN << 1][MAXN << 1],f[MAXN],pw[MAXN],h[MAXN][MAXN << 1][MAXN << 1];

/*
g[t][i][j]表示时间t到了(i,j)的方案数,f[t]表示时间t第一次到(i,j)的方案之和
h[t][x][y]表示先到(a,b)再到(a+x,b+y)的(a,b)方案数之和(i时刻在(a+x,b+y)) 
*/

int mul (int a,int b){return 1ll * a * b % mod;}
int dec (int a,int b){return a >= b ? a - b : a + mod - b;}
int add (int a,int b){return a + b >= mod ? a + b - mod : a + b;}
int qkpow (int a,int b){
	int res = 1;for (;b;b >>= 1,a = mul (a,a)) if (b & 1) res = mul (res,a);
	return res;
}
void Add (int &a,int b){a = add (a,b);}
void Sub (int &a,int b){a = dec (a,b);}

signed main(){
	read (n,w1,w2,w3,w4);int sum = (w1 + w2 + w3 + w4) % mod;
	g[0][n][n] = pw[0] = 1;for (Int i = 1;i <= n;++ i) pw[i] = mul (pw[i - 1],sum);
	for (Int t = 1;t <= n;++ t)
		for (Int x = -(t - 1);x <= (t - 1);++ x)
			for (Int y = -(t - 1);y <= (t - 1);++ y){
				int tmp = g[t - 1][x + n][y + n];
				Add (g[t][x + 1 + n][y + n],mul (tmp,w1));
				Add (g[t][x - 1 + n][y + n],mul (tmp,w2));
				Add (g[t][x + n][y + 1 + n],mul (tmp,w3));
				Add (g[t][x + n][y - 1 + n],mul (tmp,w4));
			}
	int d1 = 0,d2 = 0;
	for (Int i = 0;i <= n;++ i){
		f[i] = pw[i];
		for (Int j = 0;j <= i - 1;++ j) Sub (f[i],mul (f[j],g[i - j][n][n]));
		Add (d1,mul (f[i],pw[n - i]));
	}
	for (Int t = 1;t <= n;++ t)
		for (Int x = -t;x <= t;++ x)
			for (Int y = -t;y <= t;++ y){
				if (x == 0 && y == 0) continue;
				for (Int i = 0;i <= t - 1;++ i)
					Add (h[t][x + n][y + n],mul (f[i],g[t - i][x + n][y + n])),
					Sub (h[t][x + n][y + n],mul (h[i][-x + n][-y + n],g[t - i][x + n][y + n])),
					Sub (h[t][x + n][y + n],mul (h[i][x + n][y + n],g[t - i][n][n]));
				Add (d2,mul (h[t][x + n][y + n],pw[n - t]));
			}
	d2 = add (d1,add (d2,d2)),write (dec (mul (d2,pw[n]),mul (d1,d1))),putchar ('\n');
	return 0;
}
posted @ 2022-09-03 21:34  Dark_Romance  阅读(124)  评论(0编辑  收藏  举报