用户工具

站点工具


2020-2021:teams:legal_string:jxm2001:contest:arc_112

Atcoder Rugular Contest 112

E - Cigar Box

题意

给定初始序列 $(1,2\cdots n)$,每次操作可以任选一个数将其移动到序列最左边或最右边。

问恰好 $m$ 次操作将序列变成 $(a_1,a_2\cdots a_n)$ 的方案数。

题解

首先最后一次操作一定是将 $a_1$ 移动到最左边,或者将 $a_n$ 移动到最右边。

假设最后先进行 $c_1(c_1\ge 0)$ 次操作都是对 $a_n$ 的操作然后再将 $a_n$ 移到最右边,于是这 $c_1$ 次操作有 $2^{c_1}$ 种方案。

于是问题转化为求 $(1,2\cdots n)$ 删去 $a_n$ 后恰好在 $m-c_1-1$ 次操作将序列变成 $(a_1,a_2\cdots a_{n-1})$ 的方案数。

假设问题转化后最后先进行 $c_2(c_2\ge 0)$ 次操作都是对 $a_{n-1}$ 或 $a_{n}$ 的操作然后再将 $a_{n-1}$ 移到最右边,于是这 $c_2$ 次操作有 $4^{c_2}$ 种方案。

更加形式的,假设所有操作删去的数为 $a_1,a_2\cdots a_l$ 以及 $a_{n-r+1},a_{n-r+2}\cdots a_n$,且假设删去的顺序固定,于是方案数为 $\prod_{i=1}^{l+r}(2i)^{c_i}$。

同时 $\sum_{i=1}^{l+r} c_i=m-l-r$,由于删去的顺序其实是不固定的,于是最终算贡献时需要乘上 ${l+r\choose l}$。

关于方案的合法性,$(1,2\cdots n)$ 删去 $a_1,a_2\cdots a_l$ 以及 $a_{n-r+1},a_{n-r+2}\cdots a_n$ 的数都未经操作。

于是剩下的排列就是 $(a_{l+1},a_{l+2}\cdots a_{n-r})$,所以只要 $a_{l+1},a_{l+2}\cdots a_{n-r}$ 单增即可计入贡献。

最后问题就剩下计算每个 $\prod_{i=1}^{l+r}(2i)^{c_i}$ 了,设 $\text{dp}(i,j)=\prod_{k=1}^{i}(2k)^{c_k}\left(\sum_{k=1}^{i}{c_k}=j\right)$,考虑枚举 $c_i$,于是有状态转移:

$$ \text{dp}(i,j)=\sum_{k=0}^j (2i)^{j-k}\text{dp}(i-1,k) $$

记录一下前缀和,即可 $O(nm)$ 完成 $\text{dp}$,最后 $O(n^2)$ 枚举 $l,r$ 统计贡献即可。

查看代码

查看代码

const int MAXN=3005,Mod=998244353;
int C[MAXN][MAXN],dp[MAXN][MAXN],a[MAXN];
int main()
{
	int n=read_int(),m=read_int();
	_rep(i,1,n)a[i]=read_int();
	C[0][0]=1;
	_rep(i,1,n){
		C[i][0]=1;
		_rep(j,1,i)
		C[i][j]=(C[i-1][j]+C[i-1][j-1])%Mod;
	}
	dp[0][0]=1;
	_rep(i,1,n){
		int s=0;
		_rep(j,0,m){
			s=(2LL*i*s+dp[i-1][j])%Mod;
			dp[i][j]=s;
		}
	}
	int ans=0;
	_rep(i,0,n){
		for(int j=n-i;j>=0;j--){
			if(n-i-j>=2&&a[n-j]<a[n-j-1])break;
			if(m-i-j>=0)ans=(ans+1LL*dp[i+j][m-i-j]*C[i+j][i])%Mod;
		}
	}
	enter(ans);
	return 0;
}
2020-2021/teams/legal_string/jxm2001/contest/arc_112.txt · 最后更改: 2021/02/28 10:30 由 jxm2001