洛谷 P9009 [入门赛 #9] 牵连的世界 (Hard Version) 题解
P9009[入门赛#9],真9。
这是一道 hack 题 ,即你需要自造符合题意的数据使题中所给程序无法 AC。
Task01
看数据范围知一切,显然有 \(-2\times 10^9 \le a_i \le 2\times 10^9\),因此 \(a_i\) 可能为负数。注意 C/C++ 中的取模 %
(mod) 运算实质上是为取余运算 (rem)
对于整型数a,b来说,取模运算或者求余运算的方法都是:
1.求整数商:$ c = \dfrac{a}{b} $;
2.计算模或者余数: \(r = a - c\times b\).
求模运算和求余运算在第一步不同: 取余运算在取c的值时,向 0 方向舍入;而取模运算在计算c的值时,向负无穷方向舍入。
——摘自百度百科
因此,当 \(a_i\) 为负奇数时,a[i] % 2
的值为 -1,造成错误。所以只要搞一个 \(a_i\) 满足 \(a_i \le 0\) 即可。
Task02
我们发现,\(p\le 10^{12}\)。而 \(\log_{2}10^{12}\approx 39.86>2^{31}-1\),因此当 \(p>\sqrt{2^{31}-1}\) 且 \(p\) 为质数时,int
会爆。写个程序发现 999999999989 这个数满足条件。
Task03
众所周知,我们经常在二分是这样取 \(mid\):
int mid = l + (r - l) / 2
而不是这么写:
int mid = (l + r) / 2
这是因为有时 \(l+r\) 很大,会爆。显然,这题就有这种特性。于是,造俩最大的数据就行了。
2
2000000000 2000000000
写在最后
如果实在不会做 hack 题,怎么办?直接无脑输出极限数据,很大概率可以过。这里的极限指数据规模及数据大小都达到极限。
Python 解
def main():
taskid = int(input())
if taskid == 1:
print("1\n-1");
elif taskid == 2:
print("999999999989")
elif taskid == 3:
print("2\n2000000000 2000000000")
if __name__ == '__main__':
main()
C/C++ 解
#include<stdio.h>
int main() {
int id;
scanf("%d", &id);
if(id == 1) printf("1\n-1");
else if(id == 2) printf("999999999989");
else if(id == 3) printf("2\n2000000000 2000000000");
return 0;
}