可爱捏/[AGC003D] Anticube
可爱捏/[AGC003D] Anticube
from CSP-S模拟5
说在前面
(数学一点也不可爱,天天被虐还不得不爱qwq)
题意
给定一个大小为 \(n\) 的集合,求问该集合内最大的 元素两两相乘不为立方数的子集 的大小。
思路
考场甚至没打\(O(2^n)\)的暴力打的\(O(n!)\)的暴力,还误以为后者更优,虽然两者结局相同,但是没有但是。
首先观察数据范围,\(n⩽ 10^5\),其值域为 \([1,1e10]\),显然需要一些优秀的算法和性质支持。
然后考虑如何实现。容易知道已经是立方数的数对集合其他元素不产生影响,根据惟一分解定理,一个数必然能拆分成若干个若干幂次的质因数相乘的形式,所以该题中如果两个数相乘的结果是完全立方数则这两个数的所有质因数分别的幂次和一定为3的倍数。而且本题中只与是否是3的倍数有关,所以可以对所有幂次\(\bmod\) \(3\) 取余再进行其他操作。已知一个数 \(a\) 至多有一个大于等于 \(\sqrt a\) 的质因数,经过一些魔法的点拨后容易知道对于一个数 \(a\),至多有2个大于 \(^3\sqrt a\)的质因子,所以考虑根号分治,在 \(1—^3\sqrt a\) 的范围内进行操作。时间空间复杂度均正确。
先用欧拉筛筛出 \(^3\sqrt10e10 \approx2160\) 范围内的质数,再分别将所有元素筛去所有素数的立方数。用 \(map\) 记录该类数(指数模3并除去素数立方数后结果相同的数称为一类数) 出现的次数。
定义\((a,b)\), \(a*b\) 为完全平方数互为反数,则它们的每个质因数幂次和都是3的倍数。分解集合中的每一个数,分别求出它们的反数。如果该数是某素数的平方的倍数,则将其反数数组乘上该素数,反之乘上该素数的平方。
计算完所有数的出现次数及其反数后统计答案。完全立方数只能出现1个故只统计1次。枚举每个数,选择该数及其反数中出现次数更多的那个出现次数进行累加。因为一个数选或不选只与其反数选或不选有关,所以各组反数之间相互独立互不影响。
一些神奇的点
\(!\)运算优先级竟然高于\(\bmod\)
每统计完一对反数记得及时清空记录数量的\(map\),避免重复计算。

浙公网安备 33010602011771号