[DP记录]AT2366 [AGC012F] Prefix Median
command_block · · 个人记录
题意 : 给定一个长为
-
|b|=n -
给出序列
答案对
考虑
若按照
对于
(这些开区间的并集会形成一个中间有些断点的区间)
于是,记
转移时,暴力枚举
现在考虑
因此,
#include<algorithm>
#include<cstdio>
#define MaxN 105
using namespace std;
const int mod=1000000007;
int n,a[105],cl[105],cr[105]
,dp[55][105][105];
int main()
{
scanf("%d",&n);
for (int i=1;i<=2*n-1;i++)scanf("%d",&a[i]);
sort(a+1,a+2*n);
for (int i=1;i<=2*n-1;i++)
cl[i]=cl[i-1]+(a[i]!=a[i-1]);
for (int i=2*n-1;i;i--)
cr[i]=cr[i+1]+(a[i]!=a[i+1]);
int m=cl[2*n-1];
dp[n][cl[n]][cr[n]]=1;
for (int i=n-1;i;i--)
for (int l=1;l<=m;l++)
for (int r=1;r<=m;r++)
if (dp[i+1][l][r]){
int sav=dp[i+1][l][r];
dp[i][l][r]=(dp[i][l][r]+sav)%mod;
//左右两侧能选择的最后一个数,一定都是 b(i+1) 本身。若选择,则不会产生新的断点。
for (int k=cl[i];k<l;k++)
dp[i][k][r+1]=(dp[i][k][r+1]+sav)%mod;
//若选择一个靠左的 bi , 则会给 r 增加一个漏洞
for (int k=cr[2*n-i];k<r;k++)
dp[i][l+1][k]=(dp[i][l+1][k]+sav)%mod;
//若选择一个靠右的 bi , 则会给 l 增加一个漏洞
}
int ans=0;
for (int l=1;l<=m;l++)
for (int r=1;r<=m;r++)
ans=(ans+dp[1][l][r])%mod;
printf("%d",ans);
return 0;
}