鹰蛋总结

本篇文章是 based on 这篇的,感谢对我的帮助:

题目是 ural 1223加强版

注意,这个文章不是正解。

这篇文章的更新日志:

2024/4/13:开坑。

好,我们进入正题吧。

问题简述

有一栋 \(n\) 层的大楼,\(m\) 个一样的鹰蛋。现在你想要知道至少几层楼才能摔坏(如果都没有摔坏算 \(n+1\)),摔坏的蛋不能用了。

简单版的 \(n,m\le 1000\);加强版 \(n,m\le 10^{18}\)

其他算法

研究一个问题,有两个方面:

  • 在保证复杂度的时候的最佳方案能想到啥?

  • 在保证最优方案的时候的最优复杂度能想到啥?

在最优化之前,我们有什么 intuitive 的算法?

如果是你,你想到的第一种是啥?

你会二分

如果二分高度,很容易发现我们可以很快确定高度,但是鹰蛋也许不够。一个 \(n\) 层楼的,\(m\) 要多少呢?

答案是 \(m\ge \lceil \log_2(n+1)\rceil\)。容易发现这个是不考虑鹰蛋个数,或者是无限多个的时候的最佳方案。

所以,我们可尝试把 \(m\) 缩小到 \(\lceil \log_2(10^18)\rceil\)\(60\) 的级别?

你会你个一个扫

如果 \(m\) 有限制,比如说 \(m=1\),我们直接从 \(1\)\(n\) 顺次尝试,这样 \(n\) 次一定可以得出结果。事实上,这个是 \(m=1\) 的最佳方案。

你会 \(m\)\(m\) 个扫

我们有 \(m\) 个鹰蛋呢!为什么不这样:第一个鹰蛋测试 \(1,m+1,2m+1,\cdots\),第二个鹰蛋测试 \(2,m+2,2m+2,\cdots\),这样不就可以比一个一个扫方便很多!

这个方案要什么复杂度?容易发现,我们先测试第一个鹰蛋,如果它挺过了 \(i\) 层,\(i+m\) 层破了,一定在 \(i+1\sim i+m\) 之间。这个实验 \(m-1\) 次即可。所以我们把最有次数缩小到 \(\lceil \frac{n}{m}\rceil+m-1\)

你会把 \(m\)\(m\) 个扫和二分结合

前面很明显可以优化啊。最后的 \(i+1\sim i+m\)\(m-1\) 个数,我们用 \(m-1\) 个鹰蛋,显然可以只用 \(\mathcal{O}(\log_2(m-1))\) 次确定答案。

虽然说这个只能优化一点点,但是又没有什么启发?

你会把 \(1\)\(1\) 个扫和二分结合

二分的弊端在于,我们没有足够的鹰蛋。如果把\(1\)\(1\) 个扫和二分配合起来,会更优吗?

我们留下一个鹰蛋,其他的鹰蛋去二分。有了 \(m-1\) 个鹰蛋的努力,我们范围缩小到了 \(\frac{n}{2^{m-1}}\)。这个东西我们用最有一个鹰蛋 \(1\)\(1\) 个扫就可以了。

容易发现,这个在 \(n\) 比较大的时候比前面优很多。

你会把 \(1\)\(1\) 个扫,\(x\)\(x\) 个扫和二分结合

前面的经验告诉我们,除以一个数贡献很大,结合算法很好。

那么,全部结合呢?

我们先用 \(m-2\) 个鹰蛋二分,然后用一个鹰蛋来“间隔”地测(我们的 \(m\)\(m\) 个扫就是间隔为 \(m\)),最后用一个鹰蛋 \(1\)\(1\) 个扫,这样会不会更优?

当然你会说,为啥必须是 \(m-2\) 个?我们先不考虑这个,考虑后半部分最优是啥,即,间隔是多少最好?问出这个问题,说明你已经不拘泥于分。

我们做一个数学分析。设分成 \(x\) 份,令 \(sz=n/2^{m-2}\),我们其实要最小化 \(f(x)=\frac{sz}{x}+x-1\)。根据小学一年级,这个是对勾函数,在 \(x=\sqrt{sz}\) 时最优。

我都说了,你已经不拘泥于二分-pre

为啥是 -pre 呢,因为这个没啥用(至少我不会)。

不是二分的第一个想到的是三分。三分的常见用法是在求一个函数在 \([l,r]\) 中的极值。因此,我想到了:如果我们能把每一种鹰蛋的强度的输入,设计一种算法,使输出的函数都是不一样的凹/凸函数?

如果我们可以这样,怎么求鹰蛋硬度呢?我们要确定一个 \(n\) 级的函数,取 \(n+1\) 个点,然后做插值就可以了。因此,我们要最小化的是我们算法生成的函数的级。

我都说了,你已经不拘泥于二分

把二分替代掉,用 \(k\) 分。这里的 \(k\) 分不是系统意义上的 \(k\) 分。我们来想一个事情:

假如你是和一个很邪恶的交互库玩这个“游戏”,它每一次可以通过你的询问(即实验)判断鹰蛋碎不碎。他想要干啥?他要:

  • 我尽量让你鹰蛋碎,这样你就没有鹰蛋实验了!

  • 我尽量让你实验很多次,这样你就没耐心了!

二分的弊端是什么?我们来看看碎和不碎的区别:

  • 碎了,那么可能的硬度区间除以 \(2\),少了一个鹰蛋。

  • 没碎,那么可能的硬度区间除以 \(2\),没少一个鹰蛋。

邪恶的交互库一定会让你碎的!那么 \(k\) 分的优点是啥?举 \(3\) 分的例子吧:

  • 碎了,那么可能的硬度区间除以 \(3\),少了一个鹰蛋。

  • 没碎,那么可能的硬度区间变成原来的 \(2/3\),没少一个鹰蛋。

也就是……碎了鹰蛋,但是可以除以 \(3\)\(3>2\);没碎鹰蛋,一还可以继续实验啊!这就可以让邪恶的交互库发愁了。

但是显然 \(3\) 分是不可取的,因为 \(3^m\) 如果小于 \(n\),就不行。那么我们怎么选择 \(k\) 呢?我们要 \(k^m\ge n\),就要取 \(k=\sqrt[m]{n}\)。如果是 \(n=10^{18},m=12\)\(k=32\) 比较才能确定可行。这个时候最劣操作次数是啥呢?是 \(\log_{32/31} 10^{18}=1306\)!这个是不是突破了很多?

你会 \(k\) 分法和 \(1\)\(1\) 个扫结合

这边的 \(k\) 分才是系统意义上的 \(k\) 分。用 \(k\) 分,确定一个数的最多操作次数是 \((k-1)\times \log_{k}(n)\),也就是说,缩小成 \(1/k^x\),我们要 \((k-1)\times x\) 次。至于这个,可以用三分法来理解。

我们来算一下\(k\) 分法和 \(1\)\(1\) 个扫结合的最劣方案数吧!同样,\(k=\sqrt[m-1]{n}\) 最优。答案是:\((m-1)\times (k-1)+\frac{n}{k^{m-1}}\)。如果把 \(n=10^{18},m=12\) 带入,\(k=43\),因此 \(11\times 42+10^{18}/(43^{11})=463\)!这个,更接近答案了!

你还有别的想法

你还有什么做法呢?比如说,不同方法的结合?

posted @ 2024-04-13 22:37  SFlyer  阅读(20)  评论(0)    收藏  举报