QOJ #7258. Random Walk Sol

题目链接

很强的计数题。

注意到实际上为 \(\sum_{\text{所有长度为 }N\text{ 的路径}} (\text{该路径访问的不同格子数})\)

显然的,对于任意一条路径,其经过的点的数目一定为 \(n + 1\) ,因此不妨对重复访问过的节点进行计数。

重复访问需要满足两个条件:1.之前到达了这个节点 2.能够走出一条回路。

可以把这个拆成三部分:走了 \(S\) 步,到达了点 \(v\) ,从点 \(v\) 走了 \(L\)之后第一次回到了 \(v\),后面随便乱走(这一定不重,原因可以自行思考得出)。

\(h_S(v)\) 表示走 \(S\) 步,到达点 \(v\) 的方案数。\(g_L\) 表示走了 \(L\) 步,第一次返回到原来位置的方案数。那么这一部分的贡献就是 \(h_S(v) \times g_L \times 4^{N-S-L}\)

因此,对于确定的 \(L\)。其总贡献就为 \(\begin{aligned} \sum_{S=0} ^{n-L} \sum_v h_S(v) \times g_L \times 4^{N-S-L} \end{aligned}\)。但是,不难发现对于确定的 \(S\),其 \(\sum_v h_S(v)\) 必然是确定的的,为 \(4^S\)。因此,贡献变成了\(\begin{aligned} \sum_{S=0} ^{n-L} 4^S \times g_L \times 4^{N-S-L} \end{aligned}\)。不妨再合并一下,就变成了 \(g_L \times (N-L+1) \times 4^{N-L}\)

因此,答案变成\((N+1)\cdot 4^N - \sum_{\substack{L=2\\L\text{ 偶}}}^{N} g_L \cdot (N-L+1) \cdot 4^{N-L}\)。也就是总的-重复的。

现在的问题变成求 \(g_L\)。令 \(f_L\) 表示走了 \(L\) 步,回到原位置的方案数。其中令\(f_0 = 1\),套用一下结论,\(f_L =\dbinom{L}{L/2}^2\) 。证明放在题解末尾。因为有\(f_L = \sum_{k=2,k为偶}^L g_k \times f_{L-k}\),所以有 \(g_L = f_L - \sum_{k=2,k为偶}^{L-2} g_k \times f_{L-k}\)。表示所有方案减去多次返回的方案。

时间复杂度:\(O(n^2)\),空间复杂度:\(O(n^2)\)

Code

注意 mod 不一定是质数,因此不能使用费马小定理。

#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false);cin.tie(0),cout.tie(0)
#define File(s) freopen(s".in","r",stdin);freopen(s".out","w",stdout)
#define LL long long
#define fi first
#define se second
const int N = 5050;
LL mod;
LL C[N][N];
int n;
LL f[N],g[N];
LL pw[N];
int main()
{
	IOS;
	cin >> n >> mod;
	pw[0] = 1;
	for(int i=1;i<=n;i++) pw[i] = pw[i-1] * 4ll % mod;
	for(int i=0;i<=n;i++){
		C[i][0] = 1;
		for(int j=1;j<=i;j++)
			C[i][j] = (C[i-1][j] + C[i-1][j-1]) % mod;
	}
	f[0] = 1;
	for(int i=2;i<=n;i+=2){
		f[i] = C[i][i/2] * C[i][i/2] % mod;	
		LL res = f[i];
		for(int j=2;j<i;j+=2){
			res = res - g[j] * f[i-j] % mod + mod;
			res %= mod;
		}
		g[i] = res;
	}
	LL ans = pw[n] * (n+1) % mod;
	for(int i=2;i<=n;i+=2){
		ans -= g[i] * 1ll * (n - i + 1) % mod * pw[n - i] % mod;
		ans = ans + mod;
		ans %= mod;
	}
	cout << ans;
	return 0;
}

证明

如何证明 \(f_L = \binom{L}{L/2}^2\)?

先令 \(L = 2m\),则返回原点,就是要我们选出 \(a\)上,\(a\)下,\(b\)左,\(b\)右,其中满足\(a+a+b+b=L\)

假设 \(a\) 确定下来,那么方案数就是 \(\frac{L!}{a!\,a!\,b!\,b!}\)。这里可能有点难以理解,不妨先想象有 \(L\) 个物体,其中表示同种方向的物体颜色相同,求摆放的方案数。先让 \(L\) 个物体乱排,那么就是 \(L!\) 中,但是同色物体交换不会是方案数增加,因此就要处以\(a!a!b!b!\)

因此$$f_L = \sum_{a=0}^{m} \frac{(2m)!}{(a!,(m-a)!)^2} = \sum_{a=0}^{m}\frac{(2m)!}{m!m!} \frac{m!m!}{(a!(m-a)!)^2} = \dbinom{2m}{m}\sum_{a=0}^{m} (\frac{m!}{a!(m-a)!})^2 = \binom{2m}{m} \sum_{a=0}^{m} \binom{m}{a}^2$$
利用公式 \(\sum_{a=0}^{m} \binom{m}{a}^2 = \binom{2m}{m}\),可以得到 \(f_L = \binom{2m}{m}^2\),也就是原式。

对于公式 \(\sum_{a=0}^{m} \binom{m}{a}^2 = \binom{2m}{m}\) 的证明,可以看 OI-wiki上 范德蒙德卷积 一栏的推论3。

后记

感谢D老师智力爆发,对着题目和jiangly的代码给出了非常详细的题解,帮助我通过了本题。

为了纪念D老师的智力巅峰,这里给出D老师的题解。感觉非常易懂。

posted @ 2026-02-26 10:43  WinterXorSnow  阅读(103)  评论(0)    收藏  举报