专栏文章

题解:P7213 [JOISC 2020] 最古の遺跡 3

P7213题解参与者 2已保存评论 1

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
1 条
当前快照
1 份
快照标识符
@min5uaur
此快照首次捕获于
2025/12/01 21:03
3 个月前
此快照最后确认于
2025/12/01 21:03
3 个月前
查看原文
我计数咋这么菜。

题目链接

解题思路 & 参考代码

贡献延后转移 trick。
首先我们容易注意到对于一个合法的初始石柱状态,最终一定只会剩下 1n1 \sim n 中的数,且每个数恰好出现一次。
具体证明就是,初始 1n1 \sim n 所有数出现 22 次,显然的,对于一个数 xx 若出现了两次,则一次操作会将其中一个 xx 变为 x1x-1,若 x1x-1 也有两个数,则其中一个 x1x-1 会变为 x2x-2,因此,一次操作后,所有的数字出现个数仍然 2\le 2,该结论成立。
考虑刻画这个形式,容易发现为遍历 i=n,n1,,2,1i = n,n-1,\dots,2,1,把最后一个 i\ge i 且之前未被标记过的数标记,最终被标记的位置就为原序列的最终石柱位置。
但是这东西不好直接做,考虑直接对着原序列 aa 进行刻画,可以发现我们可以直接遍历 i=2n,2n1,,2,1i = 2n,2n-1,\dots,2,1,同时在遍历过程中维护一个集合 SS,如果此时 SS 中包含了 1,2,3,,ai1,2,3,\dots,a_i,那么 ii 不能被加入 SS 内,否则我们可以往 SS 内加入一个最大的 ai\le a_i 的不在 SS 中的数,设其为 aia_i'(若没有则 ai=0a_i' = 0),此时 ii 为其中一个最终石柱位置。
容易注意到这两个东西事实上是等价的,所以这样是对的。
刻画完后,我们可以考虑 dp。
为了方便,我们在下文转移时钦定所有数均是不同的,最后将答案乘上 12n\displaystyle\frac{1}{2^n} 即可。
假设从后往前第 ii 个位置之前(不含第 ii 个位置)已经有 s0s_0 个位置不为最终石柱位置,s1s_1 个位置为最终石柱位置。
fi,jf_{i,j} 表示考虑了后 i2ni \sim 2n 个数,SS 中含有 1j1 \sim j 且不含有 j+1j+1 的方案数,考虑如何转移 fi,jf_{i,j}
  • 如果我们钦定第 ii 个位置不为最终石柱位置,那么权值可以从 1j1 \sim j 中选取,由于之前最终石柱位置选取了 jj 个,不在最终石柱位置的位置有 s0s_0 个,那么方案数就为 (js0)(j - s_0),有转移: (js0)fi+1,jfi,j(j-s_0)f_{i+1,j} \to f_{i,j}
  • 如果我们钦定第 ii 个位置为最终石柱位置,可以进行以下分讨:
    • aiai>j+1a_i \ge a_i' > j + 1,考虑延后转移,即: fi+1,jfi,jf_{i+1,j} \to f_{i,j}
    • 否则有 ai=j+1a_i' = j + 1,那么此时 jj 会改变,枚举 jj 变为了 k[j+1,s1+1]k \in [j+1,s_1+1],那么我们需要把延迟转移的 aa' 拿来填 [j+2,k][j+2,k]
      • 显而易见的,决定延迟转移的柱子数量为 (s1j)(s_1 - j),选其中的 k(j+2)+1=kj1k - (j + 2) + 1 = k-j-1,为 (s1jkj1)\displaystyle\binom{s_1 - j}{k-j-1}
      • 然后我们需要考虑 aia_i 必须要满足 ai=j+1aika_i' = j + 1 \le a_i \le k,有 (kj+1)(k - j + 1) 种方案。
      • 这里我们需要设一个 gxg_x 表示有 xx 根柱子,操作后高度 aa' 连续的方案数,因此我们需要带一个 gkj1g_{k-j-1} 的系数,有转移: fi+1,j(s1jkj1)(kj+1)gkj1fi,kf_{i+1,j}\displaystyle\binom{s_1 - j}{k-j-1}(k - j + 1)g_{k-j-1} \to f_{i,k}
考虑如何转移 gxg_x,可以枚举第一根柱子的最终高度 ii,然后之后的 x1x-1 根柱子需要选取 i1i-1 个位置,方案数即为 (x1i1)\displaystyle\binom{x-1}{i-1},同时容易注意到 <i<i>i>i 的部分是相互独立的,所以可以直接乘上 fi1fxif_{i-1}f_{x-i},考虑 a1a_1 的方案数,ia1i \le a_1 初始有 2(xi1)2(x-i-1) 种,由于有 xix-i 种已经被选过了,因此还剩下 (xi+2)(x - i + 2) 种,因此有转移:
gx=i=1x(x1i1)gi1gxi(xi+2)g_x = \displaystyle\sum_{i=1}^{x} \binom{x-1}{i-1} g_{i-1} g_{x-i} (x-i+2)
于是就做完了,时间复杂度 O(n3)O(n^3)
参考代码CPP
ll n,m;
ll vis[1210],f[1210][1210],g[1210];
ll s0,s1;
void solve()
{
	cin>>n;
	forl(i,1,n)
		vis[rd()]=1;
	m=n*2;
	g[0]=1;
	forl(x,1,m)
		forl(i,1,m)
			add(g[x],g[i-1]*g[x-i]%mod*C(x-1,i-1)%mod*(x-i+2)%mod);
	f[m+1][0]=1;
	forr(i,m,1)
	{
		if(vis[i])
		{
			forl(j,0,s1)
			{
				add(f[i][j],f[i+1][j]);
				forl(k,j+1,s1+1)
					add(f[i][k],f[i+1][j]*C(s1-j,k-j-1)%mod*(k-j+1)%mod*g[k-j-1]%mod);
			}
			s1++;
		}
		else
		{
			forl(j,s0,n)
				add(f[i][j],(j-s0)*f[i+1][j]%mod);
			s0++;
		}
	}
	cout<<pw(pw(2,n,mod),mod-2,mod)*f[1][n]%mod<<endl;
}

评论

1 条评论,欢迎与作者交流。

正在加载评论...