题解 AT4515 [AGC030F] Permutation and Minimum

题意

有一个 (2 N) 个数的序列 (A),从 (1)(2 N) 标号。你要把 (1 sim 2 N) 这些数填进去,使它形成一个排列。

但是已经有一些位置强制填了特定的数了,输入时会给出。

最后令长度为 (N) 的序列 (B) 为:令 (B_i = min{A_{2 i - 1}, A_{2 i}})

询问所有方案中能得到的不同的 (B) 的数量。

(1 le N le 300)

思路

我们把((A_{2i},A_{2i-1}))称作第(i)对数。显然,一对数只有至少一个数为-1,才会对答案有贡献

接着就是这些有答案贡献的对填空,将没有填的数字从大到小排序来考虑

为什么是从大到小填?假设从小到大填,假设填了一个数对((i,-1)),你会发现这个数对无论填(i+1)还是(i+2),实际上方案数并没有增加,而我们会重复计算,具有后效性。但从大到小并没有这种担忧,可以始终保证答案不重不漏

(f(i,j,k))表示当前考虑到第(i)个数,还剩(j)个只填了1个数的对(不包含被限定一位的对),称作((-1,a)),(k)个原本就限定了一位的对,称作((-1,x))

考虑前(i-1)个数已经讨论,现在考虑第(i)个数,进行分类讨论

如果它是((-1,x))中的(x)(也就是被限定的数字),那么它可以不匹配,(f(i-1,j,k))转移到(f(i,j,k+1)),也可以匹配与一个填了一个数的((-1,a))匹配,那么(f(i,j,k))转移到(f(i,j-1,k))

如果不是,那么它可以不匹配,(f(i-1,j-1,k))转移到(f(i,j,k));也可以填入((-1,a))(f(i-1,j+1,k))转移到(f(i,j,k));还可以填入((-1,x)),因为任意(x)的位置固定,所以会有(k+1)种填入方案,((k+1) imes f(i-1,j,k+1))转移到(f(i,j,k))

然后我们就讨论完了,初状态(f(0,0,0)=1)

又因为原本都是-1的数对是无序的,所以最终答案还得乘上原本都是-1的数对个数的阶乘

感悟

从这一题中我们可以发现,设计状态转移方程的时候,不一定要以“如何计算出某一个状态入手”,也可以换一个思路,思考“这一个状态可以更新哪些后面的状态”,根据具体情况来选择更加简单,顺畅的思路

代码

#include<bits/stdc++.h>
using namespace std;
int const MAXN=610,MOD=1e9+7;
int n,cnt1,cnt2,m,ans=1;
int a[MAXN],vis[MAXN],f[MAXN][MAXN][MAXN];
void add(int &x,int y){x+=y;if(x>=MOD)x-=MOD;}
int main(){
	scanf("%d",&n);n*=2;
	for(int i=1;i<=n;i++)scanf("%d",&a[i]);
	for(int i=1;i<=n;i+=2){
		if(a[i]>-1 &&a[i+1]>-1){
			vis[a[i]]=vis[a[i+1]]=2;
		}else if(a[i]<0 && a[i+1]<0){
			cnt1++;
		}else{
			cnt2++;
			if(a[i]>-1)vis[a[i]]=1;
			if(a[i+1]>-1)vis[a[i+1]]=1;
		}
	}
	for(int i=n;i>=1;i--){
		if(vis[i]<2)a[++m]=i;
	}
	f[0][0][0]=1;
	for(int i=1;i<=m;i++){
		for(int j=0;j<=n;j++){
			for(int k=0;k<=n;k++){
				if(vis[a[i]]==1){
					if(k)add(f[i][j][k],f[i-1][j][k-1]);
					add(f[i][j][k],f[i-1][j+1][k]);
				}else{
					if(j)add(f[i][j][k],f[i-1][j-1][k]);
					add(f[i][j][k],f[i-1][j+1][k]);
					add(f[i][j][k],1ll*f[i-1][j][k+1]*(k+1)%MOD);
				}
			}
		}
	}
	ans=f[m][0][0];
	for(int i=1;i<=cnt1;i++)ans=1ll*ans*i%MOD;
	printf("%d
",ans%MOD);
	return 0;
}

参考资料

yyb的博客

万神的博客

原文地址:https://www.cnblogs.com/fpjo/p/13958625.html