首页 > 其他分享 >[ABC217F] Make Pair 题解

[ABC217F] Make Pair 题解

时间:2024-03-01 20:23:45浏览次数:27  
标签:方案 int 题解 Make 区间 Pair ll dp

[ABC217F] Make Pair 题解

思路解析

通过 \(n \le 200\) 和 “选出的两个学生离开队列,空出来的位置左右合拢” 这两个细节可以想到能用区间 dp 做,\(f_{i,j}\) 表示将 \(i \to j\) 这个区间全部选完的方案数,然后常规区间 dp,加一个判断如果当前区间 \([l,r]\) 中 \(l,r\) 是朋友,就可以从 \([l+1,r-1]\) 推过来,于是加上 \(f_{l+1,r-1}\) 代表除去两个端点后的区间方案数。

接下来是重点,就是遍历每一个 \(k\),然后统计 \(f_{l,k}+f_{k+1,r}\),表示枚举每一个中间点,统计从该点切割开来的两半的贡献。如果对于这一点不太理解,建议去做 P1063 [NOIP2006 提高组] 能量项链 学习区间 dp。但是题目要求方案数,就很有可能出现判重,例如:

这体现了一个区间 \([l,r]\) 的学生示意图,圆圈代表学生,连线代表他们是朋友关系,线上的数字用于区分标记。接下来有几种可能的 \(k\) 的取值。

这种情况下可能出现的方案有:【1,2,3,4】,【2,1,3,4】,【1,3,4,2】……

这种情况下的方案则和上一种情况一模一样,原因则是因为我们没有给 \(k\) 的可能性做一个判断。可以想到我们的 \(k\) 的取值一定会与端点有联系,于是在转移前判断 \(k\) 是否与 \(l\) 连接,这样就可以有效排除掉重复的方案,因为我们需要统计的根本是和 \(l\) 联系的那一部分(例如我的例子中的 1 号朋友)加上和 \(l\) 没联系的部分(例如我的例子中的2,3,4),这样就可以排除掉 \(k\) 与当前 \(l\) 无关的重复方案。

最后就是由于是算方案数,就说明区间 \([l,k]\) 和 \([k+1,r]\) 中每一种可能的方案在两段合并到一起后当前方案中的元素出现的相对顺序不会改变,例如:

左边的 1,2,3 代表区间 \([l,k]\) 中的一种可行方案,右边的 a,b 代表区间 \([k+1,r]\) 中的一种可行方案,那么当两者合并后的可行方案的顺序就有可能是:

这里不放出 a,b 是因为合并后原来一个方案中的相对顺序不会改变,画出横线是为了更好理解其实这就是一个在横线中填入相对顺序有序数字的一个问题,其实这个例子的方案数就是 \(\mathrm{C}_5^3\),扩展到所有方案就是 \(\mathrm{C}_{len/2}^{(k-l+1)/2}\)。于是便在状态转移时乘上该式即可。

时间复杂度:三层区间 dp,每层最大都是 \(n\),复杂度 \(O(n^3)\)。

code

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N = 1010;
const ll mod = 998244353;
ll n, m, f[N][N], c[N][N];
bool frd[N][N];
int main() {
	cin >> n >> m;
	n *= 2ll;
	for(int i = 1, a, b; i <= m; i++) {
		cin >> a >> b;
		frd[a][b] = frd[b][a] = true;	//标记为朋友
	}
	for(int i = 1; i <= n; i++) f[i + 1][i] = 1;
	c[0][0] = 1;
	for(int i = 1; i <= n; i++) {
		for(int j = 1; j <= i; j++) {
			c[i][j] = (c[i - 1][j - 1] + c[i - 1][j]) % mod;	//预处理组合数
		}
	}
	for(int i = 2; i <= n; i += 2) {
		for(int l = 1, r = l + i - 1; l + i - 1 <= n; l++, r++) {
			if(frd[l][r]) f[l][r] = f[l + 1][r - 1];	//小特判
			for(int k = l + 1; k <= r - 1; k += 2) {
				int l1 = (k - l + 1) / 2, l2 = (r - k) / 2;
				if(frd[l][k]) {	//去重的关键
					f[l][r] = (f[l][r] + ((f[l + 1][k - 1] * f[k + 1][r]) % mod * c[i / 2 + 1][l1 + 1]) % mod) % mod;	//注意要乘上组合数
				}
			}
		}
	}
	cout << f[1][n];
	return 0;
}

标签:方案,int,题解,Make,区间,Pair,ll,dp
From: https://www.cnblogs.com/2020luke/p/18047860

相关文章

  • P4690 [Ynoi2016] 镜中的昆虫 题解
    题目链接:镜中的昆虫经典题了,我们首先回顾下颜色数的常见做法统计:对每个位置维护一个\(pre_i\),表示与当前位置相同的颜色上一次出现位置。那么我们分讨一下。查询\([l,r]\)得到颜色数,对于\(pre_i<l\)的\(i\)点,显然它就是这个区间内\(a_i\)对应颜色出现的第一个位置,我们......
  • window.open 循环下载多个文件会打开新页签问题解决
     批量下载文件,循环使用window.open(url)的方式会打开新页签,参考了一位大侠的文章,使用iframe可以的:https://blog.csdn.net/nanke_yh/article/details/125145717如下:fileList.forEach(file=>{//同时下载多个文件,使用iframe下载,因为window.open或者a......
  • $\text{20240301}$ 字符串练习题解
    \(\text{20240301}\)字符串练习题解一定要写冬令营的题吗?遗憾的。P9717给了一个\(n\)个数的首尾相接的字符串,求若干个操作后能形成的不同的字符串大小。一次操作定义为:将字符串内所有的\(\text{01}\)同时改成\(\text{10}\),如图。通过这张图我们似乎发现了一个规律,这......
  • 关于pacemaker-集群-token-网络心跳检测时间的修改
    在笔者操作系统Redhat8.8中,pacemaker默认的token时间为3000毫秒,也可以理解成心跳检测时间这样根据默认的规则,consensus有时间如果没有特别指定的话,将是token*1.2,即3600毫秒[root@azdb01qq-5201351]#corosync-cmapctl|grep'totem.token\|consensus'runtime.config.tote......
  • CF1937D Pinball 题解
    题目链接:https://codeforces.com/contest/1937/problem/D题意简述一个长为n的格子,用'<'或'>'组成的字符串表示,在位置i放一个小球,当前所在位置是'<'则下一秒左移一步,否则下一秒右移一步。小球移动后,之前位置的符号反转,'<'变成'>','>'变成'<',直到小球离开整个......
  • [CF1804F] Approximate Diameter 题解
    题目链接题目分析显然图结构不太好维护,容易想到维护树结构。维护生成树看起来就不太靠谱,容易想到维护最短路树。keyobservation:我们固定一个端点(不妨为\(1\)),求出这个点到每个点的最短路长度的最大值\(x\)。则一定有\(\lceil{d\over2}\rceil\lex\led\)。证明:显然\(x\l......
  • CF1827C Palindrome Partition 题解
    CF1827CPalindromePartition题解题面题目传送门。称一个字符串是好的,当且仅当它是一个长度为偶数的回文串或由若干长度为偶数的回文串拼接而成。给定一个长度为\(n\)的字符串\(s\),求有多少\(s\)的子串是好的。$1\len\le5\cdot10^5$,\(s\)仅包含小写字母。......
  • P6185 序列 题解
    如果发现自己莫名其妙错了,可能是代码UB,还开O2!!!!!!!!!!!传送门首先,对于每个操作2,将\(u_i,v_i\)连边。连边之后每个连通块内部可以在总和不变的情况下任意改变。用并查集将每个连通块缩点,然后对于每个操作1,将\(u_i,v_i\)连边。得到的图又会分成若干个连通块。判断整个图是否可行,只......
  • [ABC238F] Two Exams 题解
    [ABC238F]TwoExams题解思路解析这题很麻烦,因为有两个维度。所以可以想到先按照第一维排序,这样就不需要考虑第二维的问题。其次再发现数据范围小,可以想到能用dp做,接下来就考虑如何dp。首先我们要知道我们遍历到了第几个公民,同时还要知道还剩下几个代表名额,同时我们还需要思......
  • P8085 [COCI2011-2012#4] KRIPTOGRAM 题解
    P8085[COCI2011-2012#4]KRIPTOGRAM题解本文原发布于2024-02-07洛谷题库P8085[COCI2011-2012#4]KRIPTOGRAM题解区,现于2024-2-29转载至博客园思路解析这道题目的主要难点在于如何判断明文中形如\(\texttt{abcb}\)的子串可以和密文\(\texttt{bcac}\)匹配,因为如果......