万能欧几里得
这个目前网上好像没有详细的教程,我来造福社会吧。
为了方便本文的叙述,做一个不严谨的规定。在本文中一个串可以对应一些信息,并且这些信息是支持合并的,即如果用表示串对应的信息,那么可以用和计算出。因此我们不妨类比字符串,将这类信息的合并看作是加法。同样的,这类信息与数字的乘法代表连续的合并。
万能欧几里得可以解决基本所有的类欧几里得问题,而且不同的问题不需要重新推式子,只需要稍作修改即可。
首先来形式化的说明一下万能欧几里得能解决的问题:
给定以及和,并给出一种信息合并的方式满足。从左至右考虑函数在内的直线并维护一个字符串,每当和(是整数)相交时在的末尾添加,每当和(是整数)相交时在的末尾添加,当经过整点时先添加后添加。求串所对应的信息。
可以发现类欧几里得问题都可以转化为上述问题。举个例子,如果我们要求:
那么从结果上来讲我们只需要知道每个串对应的,考虑对两个串进行合并,那么对于后面的串来讲就变成了,其中,分别是前面的串中和最终的值。那么显然为了合并和也是需要维护的。
进一步考虑,考虑到和都可以由后面的串的直接得到因此无需维护,只需要再对进行维护即可。维护的计算方式稍加推导即可得知。
我们将解决上述问题的方法表示为(其中、分别表示、),考虑如何递归至更小的规模:
首先可以发现,我们将对取余是没有关系的(因为不会改变),于是可以保证。
接着,如果考虑如何转化为。发现这或许可以通过将坐标系的横纵轴翻转解决。我们设,那么可以考虑先处理好值域在之间的部分。如果,那么不会经过,我们直接返回。否则我们将坐标轴反转并平移,可以使之前的问题等价于函数在之间的部分,此时我们需要将与互换。不过这里有一个问题是互换了和以后,如果经过了整点那么实际的顺序会与我们规定的相反,为了解决这个问题,我们将函数整体向下平移,即变成,那么原来的经过整点就变成了先与相交的情况,和我们期望的一致,并且对其它的经过方式都不会产生结果上的变化。当然这会对头尾的需要单独处理的一小部分产生一些影响,接下来会说明这个问题。现在我们可以递归到。
接下来还需要处理首尾的问题。先考虑开头,由于我们已经处理了值域在之后的,那么与相交的情况只会出现一次,于是我们统计与相交的次数,那么就是函数与相交的点的横坐标的下取整即。不过需要特别注意的是当为整数时,我们经过了这个整点,而由于我们之前将递归的函数下移了,因此递归的部分实际上会将与相交的情况包含,因此我们在开头需要计算的与相交的次数只有次,之后再与相交。即,在开头需要额外添加的信息是。
尾部的问题也是类似的。由于函数值的整数部分不会再增加,于是只有与相交的情况。计算可得与相交的点横坐标为,由于递归下去的函数平移了因此我们实际上只处理到了,于是我们在末尾加上即可。
于是我们可以保证,考虑怎么解决这一部分。
我们设,那么原函数可以表示为,将其与函数相比,相当于在每次经过之前额外经过次。于是我们可以递归至。
综上所述,我们完整的解决了万能欧几里得问题。为了使思路更加清晰,我们用伪代码的形式重新整理一遍之前的方法。
如果将维护信息的加法和乘法的复杂度看作,那么万能欧几里得的复杂度与欧几里得算法的分析相似,为。值得注意的是通常为了方便乘法可以用倍增进行快速乘,不过如果分析系数与乘数的关系可以得到更快的方法。
用平移的方式处理特殊要求的方法是嘿嘿嘿同学告诉我的,嘿嘿嘿太强了。