一、题目
题干描述的比较奇怪,看到浮点数也不知道是什么意思,没见过这种题型
点进去看
题目的意思是让我们用6和9构造出20,但是很容易看出来,6s+9t = 20这个方程是没有整数解的,因为20不是3的倍数
这里正常方法肯定是不行的,估计会有骚操作
二、解题
F12检查元素
试试把 min 的值改为负数,提交了一个负数上去
后台不认,那么肯定是有检测机制的
再试试输入小数
小数也不行
我做出这题的灵感来源于室友,他告诉我,当在9斤的瓜那里输一个很大的数时,提交上去会变成一个负数,如下:
而这个负数其实非常特殊,因为它正好是long long int 的最小值
正常情况下是不可能出现负数的
也就是说,我们如果输入一个很大的值,会造成溢出,这个地方就可以做工作了
用这个-9223372036854775808除以9,将得到的数取整输入进去,不会造成溢出,但是将这个数再+1就会造成溢出了,对6同理
我们选择用9乘以大数造成溢出,再用6加回来,直到6s+9t = 20-(-得到的负数)有整数解
直接操作
第一步:9乘大数溢出
第二步:6乘那个上面在计算器得到的取整后的数
得到-2了,那么下一次可以选择构造出-4,或者用6再梅开二度
第三步:6梅开二度
可以看到这里再减去一个 9223372036854775808时,就刚刚好会出现-4,也就是我们需要的24
第四步:9乘以大数溢出出
第五步:6*4加回去补上-4
拿到flag
三、总结
1. 这种题型确实挺新奇的,不过尝试的次数会很多很多,我在寝室里骂了出题人一个下午
2. 实际上这题对猜后台代码的能力有一定要求,看看官方给出的wp
function action()
{
check_last_action();
$bottle_6 = intval($_POST['b6']);
$bottle_9 = intval($_POST['b9']);
if ($bottle_6 < 0 || $bottle_9 < 0) {
die('操作无效:不能放负数个瓜。点击<a href="/">这里</a>回到主页。');
}
$_SESSION['pool'] += intval($bottle_6 * 6 + $bottle_9 * 9);
header('Location: /');
}
根据 PHP 文档 Integer 整型,PHP 在运算结果超出 int 范围时,会返回 float 类型,进一步使用函数
intval()
来把 float 转为 int 时,如果这个 float 超出了 int 范围(定义在PHP_INT_MAX
),结果是未定义的,在其评论中有一条Be aware of float to int cast overflow
列举了一些溢出后的转换结果,选手也可以自己尝试。在尝试的过程中,只要能产生一个模 3 余 2 的重量(如 2, -1 等)都可以很容易凑到 20。
其实我在试的时候是出现了科学计数法表示的大数,当时想着通过这个来突破,但是也不行,一加回去又变成0了,后来看到官方wp后才知道,一旦这个数小于-9223372036854775808,就会变成后台定义的科学计数法表示,这是个坑
3. 果然是中科大,能想到个出这种题,不过也不算纯web,多少是沾点数论和编程了