【比赛】【SMOJ 2019.1.21】
没错,全世界都\(\mathrm{AK}\)了。
这题不难。直接严格分一下类,看看\(k\)个人、\(k+1\)个人、\(k+2\)个人都错开的方案数即可。
很裸的容斥原理题啊。
唯一的坑点就是在处理\(\mathrm{lcm}\)的时候,如果\(\mathrm{lcm}\)已经超过了上界\(\mathrm{R}\),就应该直接退出,不然会溢出。
十 年 O I 一 场 空 , 不 看 题 意 见 祖 宗 。
看清题意之后其实也不难啊。
-
对于每组数据,预处理出\(\mathrm{f[i][j]}\)表示在\(i\)个数位中凑出和为\(j\)的数字的方案数,时间复杂度是\(\Theta (n^2k^2)\)的,毫无压力、
-
然后回到题意,先算出 前\(n\)个数字的总和等于最后\(n\)个数字的总和的方案数 和 下标是奇数的所有数字的总和等于下标是偶数的所有数字的总和 的方案数的和,再减去同时满足这两种规则的方案数即可。
连题都不看清楚,果然可以退役。
这题刷新了我程序的细节方面的上限了……
不过本身的算法并不难,就是直接枚举\(k\)个字符串“压”在一起,然后“压”好的字符串(假设这个字符串存在)有多少种可能是可以直接算出来的。
但题目要求了构造出的字符串只能匹配\(k\)个字符串,所以我们还要再看看构造出的这些可能的字符串中有哪些是和剩下\(n-k\)个字符串是能够匹配的,但是因为一个构造出的字符串可能和多个字符串匹配,所以我们还要再容斥一下。
所以就是 \(01\)二进制枚举(也可以用\(\mathrm{DFS}\)实现)+容斥原理,虽然细节巨多,但总比扮演方案这种题目要简单。
被思维定式带到了容斥原理了,结果比赛完一想才发觉简单得要死……
用\(\mathrm{f[i][j]}\)表示 当前放了数字的位置的二进制状态为\(i\),且最后一个放进去的数为\(a[j]\)的方案数。然后就直接枚举\(a[j]\)能够放进\(i\)中的哪一位即可。
但是最终的答案不是\(\mathrm{f[(1<<n)-1][n]}\),因为整个数组中肯定会有重复的元素,这个时候就要像求可重集排列一样把这些多余元素的全排列的积除掉。