首页 > 其他分享 >[AGC030F] Permutation and Minimum 题解

[AGC030F] Permutation and Minimum 题解

时间:2023-10-12 19:37:46浏览次数:43  
标签:匹配 int 题解 情形 Minimum AGC030F 东西 序列 sur

Permutation and Minimum

看到 300 的数据范围,再加上计数题,很容易就往计数 DP 方向去想。

为方便,我们将 \(n\) 乘二。

因为是两个位置取 \(\min\),于是我们便想到从小往大把每个数填入序列。于是DP数组第一维的意义便出来了:当前已经填入了前 \(i\) 小个数。

考虑当前填入一个数。这个数有两种可能:一是与比它小的数匹配,此时最小值已经确定了,是那个更小的数,而更小数已经被填入序列,所以当前数与哪个比它小的数匹配根本不影响。二是与比它大的数匹配——此时最小值不确定,因此与不同的比它大的数在不同位置匹配会有不同结果。

于是我们便依次设出了剩余两维的意义:前 \(i\) 位中有 \(j\) 个东西是确定的(指与它配对的东西以及这一对数所在的位置都被确定,不论这确定的对是后来填出的还是初始序列中就已经给出的;若初始序列中只给出了一半的数,不算作此类),\(k\) 个东西是固定的(指其所在的位置固定,但与其配对的东西尚未被确定,显然此种情形下与其匹配的东西应是一个未在原序列中出现的东西),则剩余 \(i-j-k\) 个东西匹配了原序列中出现的东西,且该另一半必比 \(i\) 大。(注意这里我们把确定和固定这两个词黑体了,因为我们接下来还要多次使用它们)

我们考虑分情况从 \(f_{i,j,k}\) 转移到 \(f_{i+1,j',k'}\)。

情形1. 若数 \(i+1\) 在序列中被给出了:

情形1.1. 若数 \(i+1\) 在序列中被给出了,且其配对也被给出了:

则此时显然其已被唯一确定,直接划归 \(j\) 类。故此种情形唯一可行转移是 \(f_{i,j,k}\rightarrow f_{i+1,j+1,k}\)。

情形1.2. 若数 \(i+1\) 在序列中被给出,但其配对未被给出:

有两种情形:其与比它小的东西匹配,或者与比它大的东西匹配。

情形1.2.1. 与比它小的东西匹配。

则依照定义,其应与 \(i-j-k\) 中某个东西匹配,且与其中不同东西匹配有影响(因为匹配的另一半是此段的最小值)。匹配完后 \(j\) 类多出了两个。则转移是 \(f_{i,j,k}\times(i-j-k)\rightarrow f_{i+1,j+2,k}\)。

情形1.2.2. 与比它大的东西匹配。

则依照定义,其应划归 \(k\) 类,留待以后处理。故 \(f_{i,j,k}\rightarrow f_{i+1,j,k+1}\)。

情形2. 若数 \(i+1\) 在序列中未被给出:

情形2.1. 作为 \(k\) 类中某个东西的另一半。

则此时与 \(k\) 类中哪个东西匹配根本不影响,因为每一对的最小值已经被确定了。因此若 \(k\) 非零,则有 \(f_{i,j,k}\rightarrow f_{i,j+2,k-1}\)。

情形2.2. 作为 \(i-j-k\) 类。

则直接划归即可,因为方案数已在 1.2.1 中被计算。故 \(f_{i,j,k}\rightarrow f_{i+1,j,k}\)。

情形2.3. 作为 \(k\) 类。

依照定义,\(k\) 类中元素的位置都是固定的。故 \(i+1\) 应被填到一个空余区间里。考虑计算此种空余区间的数量。

显然,总序列中,若我们设 \(sur_i\) 表示填入前 \(i\) 个数后序列中剩余的确定的数(即原序列中给出的已经确定好的数对),则目前一共有 \(j+sur_i\) 个数已经确定。\(k\) 类中已有的东西每个都占掉了 2 个格子,故还得减去 \(2k\);再令 \(sig_i\) 表示填入前 \(i\) 个数后剩余的固定的数(即原序列中给出的确定好一半的数对),显然其也各占去 2 个格子;又因为同一个区间里两个数的顺序无影响,所以还得除以 2。所以我们最终得到了空余区间的数量为 $\dfrac{n-(j+sur_i)-2k-2sig_i}{2} $。若设其为 \(spr\),则有 \(f_{i,j,k}\times spr\rightarrow f_{i+1,j,k+1}\)。

显然转移 \(O(1)\);于是复杂度 \(O(n^3)\) 解决。

#include<bits/stdc++.h>
using namespace std;
const int mod=1e9+7;
const int N=610;
int n,a[N],p[N],f[2][N][N];
int sig[N],mat[N],sur[N];
int main(){
    scanf("%d",&n);
	n<<=1;
    for(int i=1;i<=n;i++) mat[i]=((i-1)^1)+1;
    for(int i=1;i<=n;i++) scanf("%d",&a[i]),p[a[i]]=i;
    for(int i=1;i<=n;i++) if(a[i]!=-1&&a[mat[i]]==-1) sig[a[i]-1]++;
    for(int i=n;i>=0;i--) sig[i]+=sig[i+1];
    for(int i=1;i<=n;i++) if(a[i]!=-1&&a[mat[i]]!=-1) sur[a[i]-1]++;
    for(int i=n;i>=0;i--) sur[i]+=sur[i+1];
    f[0][0][0]=1;
    for(int i=0;i<n;i++){
        memset(f[!(i&1)],0,sizeof(f[!(i&1)]));
        for(int j=0;j<=i;j++){
			for(int k=0;j+k<=i;k++){
            	if(n-(j+sur[i])-k*2-sig[i]*2<0)continue;
            	if(!f[i&1][j][k])continue;
            	if(p[i+1]){
                	if(a[mat[p[i+1]]]!=-1){f[!(i&1)][j+1][k]=f[i&1][j][k];continue;}
                	(f[!(i&1)][j][k+1]+=f[i&1][j][k])%=mod;
                	(f[!(i&1)][j+2][k]+=1ll*(i-j-k)*f[i&1][j][k]%mod)%=mod;
            	}else{
                	if(k)(f[!(i&1)][j+2][k-1]+=f[i&1][j][k])%=mod;
                	(f[!(i&1)][j][k]+=f[i&1][j][k])%=mod;
                	(f[!(i&1)][j][k+1]+=1ll*(n-(j+sur[i])-k*2-sig[i]*2)/2*f[i&1][j][k]%mod)%=mod;
            	}
        	}   
        }
    }
    printf("%d\n",f[n&1][n][0]);
    return 0;
}

标签:匹配,int,题解,情形,Minimum,AGC030F,东西,序列,sur
From: https://www.cnblogs.com/xuantianhao/p/17760363.html

相关文章

  • 洛谷P3576 [POI2014] MRO-Ant colony 题解
    MRO-Antcolony根据下取整除法的性质\((\left\lfloor\dfrac{\left\lfloor\dfrac{x}{y}\right\rfloor}{z}\right\rfloor=\left\lfloor\dfrac{x}{yz}\right\rfloor)\),我们可以反向考虑,即从特殊边开始,计算出从每个叶子到特殊边的路径上,要除以的那个分母是什么。这个可以直接一遍df......
  • 洛谷P3713 [BJOI2017] 机动训练 题解
    机动训练这题的瓶颈,在于把\(a_i^2\)看作\(\sum\limits_{i=1}^{a_i}\sum\limits_{j=1}^{a_i}1\),然后我们就可以看成“两两相同的机动路径都能贡献1”。于是我们设\(f_{x1,y1,x2,y2}\)表示两条起点为\((x1,y1)\)和\((x2,y2)\)的相同路径的数量,然后分别枚举两条路径的方向......
  • [AGC013E] Placing Squares 题解
    PlacingSquares关键是将问题从抽象的“正方形面积”转为具象的形式:一段长度为\(d\)的区间,有两个不同的小球要放进去,则总放置方案就是\(d^2\),且不同的区间间方案是通过乘法原理结合的,刚好是题目中\(\prodd^2\)的形式。于是我们可以设计DP:设\(f_{i,j}\)表示前\(i\)个......
  • 洛谷P3118 [USACO15JAN] Moovie Mooving G 题解
    MoovieMoovingG设\(f[i][S]\)表示在第\(i\)场(注意是场,不是部)电影时,已经看了\(S\)里面的电影是否合法。然后贪心地取\(|S|\)最小的状态保存。光荣MLE了,\(21\%\)。发现当一场电影结束后,无论这一场是在哪里看的都没关系。因此我们设\(f[S]\)表示只看集合\(S\)里......
  • CF908D New Year and Arbitrary Arrangement 题解
    NewYearandArbitraryArrangement思路:期望题果然还是恶心呀!我们设\(f[i][j]\)表示当串中有\(i\)个\(a\)和\(j\)个\(ab\)时的方案数。为了方便,设\(A=\dfrac{P_a}{P_a+P_b},B=\dfrac{P_b}{P_a+P_b}\)。显然,可以这样转移:\[f[i][j]=f[i+1][j]\timesA+f[i][i+j]\ti......
  • CF264B Good Sequences 题解
    GoodSequences状态很显然,设\(f[i]\)表示位置\(i\)的最长长度。关键是转移,暴力转移是\(O(n^2)\)的,我们必须找到一个更优秀的转移。因为一个数的质因子数量是\(O(\logn)\)的,而只有和这个数具有相同质因子的数是可以转移的;因此我们可以对于每个质数\(p\),设一个\(mx_p......
  • Maximums and Minimums (CF E)
      思路:分别求出最小区间和最大区间,利用单调zai处理即可然后在利用调和级数,求最小值的倍数 后记:为什么我不2个元素都求一个区间呢?......
  • 题解 AtCoder wtf22_day1_b【Non-Overlapping Swaps】
    题解AtCoderwtf22_day1_b【Non-OverlappingSwaps】problem给定一个排列,要求交换最多\(n-1\)对元素,使得这个排列变成[1,2,...,n]的有序排列。当然没有那么简单,对于交换还是有限制的,对于相邻的两次交换,不妨叫做\((l_i,r_i)\)和\((l_{i+1},r_{i+1})\),必须满足这两个交......
  • 题解 CF486D Valid Sets
    题目链接相当牛逼。这种找数量的题型,确定树形\(dp\)没跑了。首先思考常规树形\(dp\),不难想到设\(f_{u,a,b}\)表示以\(u\)为根节点的子树内(包括点\(u\)),最大值是\(a\),最小值是\(b\)的连通子图数量,转移很容易,但是这样时间空间复杂度是\(\rmO(n^3)\),而且无论是状态上......
  • Debian12安装elasticsearch实践及问题解决方案
    一、安装安装其实很简单,直接上官网链接:下载地址,官网提供了所有安装方式,总一款适合你。我的目标系统是Debian12,包管理是apt-get,所以就以这个为示例,仅供参考。1、先选择需要安装的版本2、导入ElasticsearchPGP密钥wget-qO-https://artifacts.elastic.co/GPG-KEY-elastic......