洛谷 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;
}
posted @ 2023-04-02 09:49  ZyIOLO  阅读(32)  评论(0编辑  收藏  举报