记一道很难的算法题解:次方塔排序

题目:https://open.kattis.com/problems/towers
原链:https://petr-mitrichev.blogspot.com/2019/06/power-towers-solution.html

The first observation is that there exists such number k that if the first tower is at least k times bigger, it will keep being at least k times bigger even if we add 2 to it and 100 to the other tower.
感觉这是一个开始。它比较的办法大概是说,矮塔用1在塔顶拔高,从上往下比较。然后如果k倍塔的下面都是2,另一个塔下面都是100,k足够大时第一个塔也会更大。(但这个跟层数有关了。)
屏幕上前两段的意思大概是,次方塔是个放大器,只要上层两数差10倍,下层无论如何都会从上层直接得出结论。他的数学推导还是有点点跳。
第二段给出了expand函数,大致意思是说,俩塔的上面部分是两个数,它们被算到任意次方(1x,2x…100x,1y…100^y)后有一堆数,这堆数排序后,如果相邻有十倍以上的数就删去(十倍以上的数),得到集合expand(S),这也可以看做是在本题中需要继续考虑下去的集合。(因为第一段论证了10倍的特殊性)
Now let’s start with the set S={1,2,…,100}, and repeatedly compute expand(S), expand(expand(S)), … It turns out that the process stops very quickly, and already expand(expand(S))=expand(expand(expand(S))), and this set has just 17709 elements!
然后这里就是最有意思的地方:这个expand函数从1到100执行下去,无数次也只能产生不到两万元素!(打开题目的钥匙)
If at some point the numbers are equal, and are at least 300, then we just need to look at the next differing number going from top to bottom, since (100/99)300>10.
这句大致说,由于(100/99)^300>10,我们还是需要看下一个不等的数

总结下:
如果x>10y,那么2x>100y(k=10)
由此产生expand函数,对各种x和y保留需要考虑的情况
expand函数对1-100的数运行三次就收敛了,总共不到两万个数
在比较次方塔的时候,只需要考虑这两万个case就好了,其余的因为第一点都可以被忽略
一个特殊情况是现在的次方塔相等且大于300,这里就只需要比较下一个不同的数,可以加快一点

下一部分就是计算这一万七千个数,由于次方的关系,这些数字还是很大的,但是可以用log计算。

当初我们研究这问题的时候第一次就想到log,但是log两次之后就会有加号,就不好log了。比如xyz,log一次成为y^zlnx,两次后是zlny+lnx,这时候就不好log了。这几位Petr Mitrichev together with Roman Elizarov and Evgeny Kapun厉害的地方就在于只用两个log+递归+一万七千个情况(计算机还是挺好处理的数量级)解决了这个问题。

当时一起想这问题的人还有一个方法是顶部用对数的一种递归,但是不对。

倒数第三段认为比较loglog的浮点运算不稳定,需要 leap of faith,这就是为啥这题没进ICPC world final。

最后是验证他思想的代码。

这题看得我有看godel’s lost letter & pvnp中对一类p!=np证明的攻击时的那种惊诧。毛子果然是icpc的最强种族。这题后面想来又不难,都是一些基础不等式、对数加上递归算法。当求两次对数还不行的时候,其实就应该想到递归了。我一开始认为这题跟kattis上exponial差不多,都是一个性质的递归,谁曾想比exponial复杂得多。初等方法的问题最难,不过看回这题,其实解法也是有迹可循的。题中给出了每个数小于100的特点,这就已经提醒了答题者。不难想象用好的数值方法这种expand函数是可以扩展的。

最后说下,petr也是想了很久。这题目我也记得了、想了很久。所以很兴奋看到有人做出来了。在之前只有topcoder上面有一个非常不完全的尝试(跟这个解法完全不一样,而且看回那个我觉得那个解法是没希望的)。我曾经设想这个的解法只可能是用某种时差攻击(timing attacks)一点点读出数据,再用更加好的计算机长时间运行找出答案(不难想见有很多好的数值算法估计log)。这个是可行的(好吧别这么做,反正在world finals上面交题目是要扣时间的),在练习的时候。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值