2018.10.3万圣节的入场券
Posted scx2015noip-as-php
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2018.10.3万圣节的入场券相关的知识,希望对你有一定的参考价值。
题目描述
[万圣节Party开始前……]
万圣节到了,LazyJazz要办一个大Party(Communist Party)!
于是LazyJazz邀请了同学朋友,远近亲戚共计 n 人,每人发了一张Party入场券。
可是到了万圣节这一天,不知怎的来了 $n+1$ 个人(果然是鬼节),而且每人手里都拿了一张入场券,这让LazyJazz十分头疼。
好在当时发入场券时,每张券上都印了一个验证码。真的入场券的验证码由一个固定合数 $x$ 乘上一个两两入场券互不相同的质数 $p_i$ 得到。
于是LazyJazz一一检视了所有人的验证码,发现了一个另类(即不满足除 x 的商为一个质数),于是保安把这个好学生恐怖分子拖了出去。
LazyJazz觉得这是很有意思,决定把他看到的所有验证码告诉你,让你猜猜哪个验证码是假的。
输入格式
第一行,一个正整数 $n (9<n)$,表示正常应到人数。
第二行,包含 $n+1$ 个用空格隔开的正整数 $Ai$,表示实际到场的 $n+1$ 个人手里的入场券上的验证码。
输入数据保证只有一个“另类”验证码,且可以判断出来。
输出格式
一个正整数,表示假的验证码。
样例
input
10
12 76 92 116 87 44 8 20 68 28 52
output
87
限制与约定
对于 30% 的数据,保证 n≤100, x≤100
对于 60% 的数据,保证 n≤1000
对于 100% 的数据,保证 n≤100000, x≤100000, pi≤1500000
输入数据保证只有一个“另类”验证码,且可以判断出来
时间限制:1s
空间限制:256MB
回来想了一下这题,感觉没有极端数据,有些细节没有考虑到就A了。
做题前置条件:
1.输入总共有 n+1 个数,别少输一个……
1.题目保证验证码乘的质数两两不相同,且数据保证只有一个不合法的验证码且可以判断出来,所以不可能存在两个相同的验证码(因为两个相同的验证码乘的质数不相同,那么乘的合数也不相同,所以两数中有一个数不合法,但不能判断出来是哪一个)。
3.题目只保证了合法的数不会超过 100000*1500000,开个 long long 完事,但没有保证那个不合法的数的大小(也就是说正常情况下应该特判输入!),不过Lazyjazz可能忘了这根筋了……没有爆 long long 的数。
4.数据保证$p_i leq 1500000$,所以一个数除以公共合数后,如果超过这个上限,不管是不是素数都不合法,输出它即可。
算法一
由于 x 比较小,你可以暴力枚举 x (当然是个合数)的值,然后再一个一个判断是否能正好甄别出一个“另类”的数,然后输出就好了
总时间复杂度取决于你判断素数的方法的复杂度,大概在O(n2⋅x)−O(n⋅x)之间
期望得分:30分。
算法二
个人感觉Lazyjazz的讲解有问题,这里不放了(可能卡掉的数据:2 6 9 15 21 33)
时间复杂度:O(n2logn)
期望得分:60分
算法三
可以发现,任意两个数都等于 一个公共合数 * 不同的素数,那公共合数就是它们的GCD(因为GCD就是两数的最大公因子,两数除以GCD后互素),那么这两个数都除以这个合数后,都应该是素数。
题目保证了只有一个不合法的数,所以对于剩下$n$个数而言,它们的公共合数只能是它们的GCD,因为只有这样每个数除以这个公共合数后才互素,才可能都是素数(如果两数不互质那至少有个数不是质数)。
所以我们可以枚举所有相邻的两个数,每次求出它们的GCD作为候选 x 值,找出一个出现次数最多的候选 x,可以证明这就是所有数的公共合数。
在两种情况下某个数是不合法的:
1.不合法的那个数与左右两数的GCD与其它对GCD都不相同(与左右两数的GCD之间可能相同)。那么找出这个错误的非大众GCD即可。
2.所有对数的GCD都相同,或只有一对数的GCD与其它对GCD都不相同 且 这个GCD对应的数对不在两端(我原来的AC代码没考虑这一点,数据可能没卡,但这样一组数据就只有一个GCD与其它的都不相同:4 6 20 10 14。可以证明,这个不合法的数是它相邻的某个数的倍数 或者是1,所以它是后边提到的非素数),这时会有一个数除以这个合数后不是素数(为什么不直接说是合数?因为1不是素数,但它也不是合数)或大于1500000,那它就是不合法的。当然,只有一个GCD不相同时,不合法的数只可能是这个GCD所对应的相邻两个数中的一个咯。
3.只有一对数的GCD与其它对GCD都不相同 且 这个GCD对应的数对在两端,那么特判两端的GCD对应的总共4个数是否合法即可。
综上,最多有两个GCD不是正确的公共合数。因此可以进一步优化枚举,只需要求出前6个数的5对GCD,正确的GCD出现次数一定最多(至少3次),因此就可以快速揪出来正确的公共合数了。
时间复杂度:O(nlogn)
期望得分:100分
另外,这题其实可以用一个看似暴力的做法写:考虑到一个合法的数等于 一个公共合数 * 一个素数,把所有验证码从小到大排序,然后把最小的数分解质因数,如果最小的数除以其一个质因子是合数且不超过100000,它才是一种可能的公共合数。用这个公共合数除其它的每个数,如果只有一个数被除后不是整数或不是素数或大于1500000,那这个数就是不合法的数。如果所有的公共因子都不能找出不合法的数,它自己就是不合法的数。(GDC的做法)
时间复杂度:O(nlogAi)
期望得分:100分
另外,今天的T2(万圣节的积木)是一道Lazyjazz神爷弱化掉了的自创题,去掉了最后5分的数据,原题最后5分的知识的难度跟前95分完全不在一个级别上,前95分难度大概在NOIP提高组水平,后5分难度大于国家集训队水平,是一道防AK神题。考虑到Lazyjazz要出售这题,为了保护版权,T2不公开(机房可能有人在luogu存题了,但那最多是今天做的95分难度代码,原题的最后5分连std都还没写过 而且题解很难看懂的)。
以上是关于2018.10.3万圣节的入场券的主要内容,如果未能解决你的问题,请参考以下文章