万能欧几里得

这个目前网上好像没有详细的教程,我来造福社会吧。

为了方便本文的叙述,做一个不严谨的规定。在本文中一个01串可以对应一些信息,并且这些信息是支持合并的,即如果用g(S)表示01串S对应的信息,那么可以用g(S)和g(T)计算出g(S+T)。因此我们不妨类比字符串,将这类信息的合并看作是加法。同样的,这类信息与数字的乘法代表连续的合并。

万能欧几里得可以解决基本所有的类欧几里得问题,而且不同的问题不需要重新推式子,只需要稍作修改即可。

首先来形式化的说明一下万能欧几里得能解决的问题:

给定p,q,r,l以及g(′0′)和g(′1′),并给出一种信息合并的方式满足g(S)+g(T)=g(S+T)。从左至右考虑函数y=px+rq在(0,l]内的直线并维护一个01字符串S,每当和x=c(c是整数)相交时在S的末尾添加′0′,每当和y=c(c是整数)相交时在S的末尾添加′1′,当经过整点时先添加′1′后添加′0′。求01串S所对应的信息。

可以发现类欧几里得问题都可以转化为上述问题。举个例子,如果我们要求:

∑i=0li⌊pi+rq⌋

那么从结果上来讲我们只需要知道每个串对应的∑i⌊pi+rq⌋,考虑对两个串进行合并,那么对于后面的串来讲∑i⌊pi+rq⌋就变成了∑(i+x)(⌊pi+rq⌋+y),其中x,y分别是前面的串中i和⌊pi+rq⌋最终的值。那么显然为了合并x和y也是需要维护的。

进一步考虑∑(i+x)(⌊pi+rq⌋+y)=(∑i⌊pi+rq⌋)+(x∑⌊pi+rq⌋)+(y∑i)+(xy∑1),考虑到∑i和∑1都可以由后面的串的x直接得到因此无需维护,只需要再对∑⌊pi+rq⌋进行维护即可。维护的计算方式稍加推导即可得知。

我们将解决上述问题的方法表示为f(p,q,r,l,s0,s1)(其中s0、s1分别表示g(′0′)、g(′1′)),考虑如何递归至更小的规模:

首先可以发现,我们将r对q取余是没有关系的(因为S不会改变),于是可以保证r<q。

接着,如果p<q考虑如何转化为p≥q。发现这或许可以通过将坐标系的横纵轴翻转解决。我们设k=⌊pl+rq⌋,那么可以考虑先处理好值域在(1,k]之间的部分。如果k=0,那么不会经过y=c,我们直接返回s0∗l。否则我们将坐标轴反转并平移,可以使之前的问题等价于函数y=qx+(q−r)p在(0,k−1]之间的部分,此时我们需要将s0与s1互换。不过这里有一个问题是互换了s0和s1以后,如果经过了整点那么实际的顺序会与我们规定的相反,为了解决这个问题,我们将函数整体向下平移1p,即变成y=qx+(q−r−1)p,那么原来的经过整点就变成了先与x=c相交的情况,和我们期望的一致,并且对其它的经过方式都不会产生结果上的变化。当然这会对头尾的需要单独处理的一小部分产生一些影响,接下来会说明这个问题。现在我们可以递归到f(q,p,q−r−1,s1,s0)。

接下来还需要处理首尾的问题。先考虑开头,由于我们已经处理了值域在1之后的,那么与y=c相交的情况只会出现一次,于是我们统计与x=c相交的次数,那么就是函数与y=1相交的点的横坐标的下取整即⌊q−rp⌋。不过需要特别注意的是当q−rp为整数时,我们经过了(1,q−rp)这个整点,而由于我们之前将递归的函数下移了1p,因此递归的部分实际上会将与x=q−rp相交的情况包含,因此我们在开头需要计算的与x=c相交的次数只有⌊q−r−1p⌋次,之后再与y=1相交。即,在开头需要额外添加的信息是s0∗⌊q−r−1p⌋+s1。

尾部的问题也是类似的。由于函数值的整数部分不会再增加,于是只有与x=c相交的情况。计算可得与y=k相交的点横坐标为kq−rp,由于递归下去的函数平移了1p因此我们实际上只处理到了kq−r−1p,于是我们在末尾加上s0∗(l−⌊kq−r−1p⌋)即可。

于是我们可以保证p≥q,考虑怎么解决这一部分。

我们设k=⌊pq⌋,那么原函数可以表示为y=kx+(pmodq)x+rq,将其与函数y=(pmodq)x+rq相比,相当于在每次经过x=c之前额外经过k次y=c。于是我们可以递归至f(pmodq,q,r,l,s1∗k+s0,s1)。

综上所述,我们完整的解决了万能欧几里得问题。为了使思路更加清晰,我们用伪代码的形式重新整理一遍之前的方法。

f(p,q,r,l,s0,s1) r=rmodq ifp<qthen k=⌊pl+rq⌋ ifk=0then returns0∗l returns0∗⌊q−r−1p⌋+s1+f(q,p,q−r−1,k−1,s1,s0)+s0∗(l−⌊kq−r−1p⌋) else k=⌊pq⌋ returnf(pmodq,q,r,l,s1∗k+s0,s1)

如果将维护信息的加法和乘法的复杂度看作O(1),那么万能欧几里得的复杂度与欧几里得算法的分析相似,为O(log⁡n)。值得注意的是通常为了方便乘法可以用倍增进行快速乘,不过如果分析系数与乘数的关系可以得到更快的方法。

P.S.用平移1p的方式处理特殊要求的方法是嘿嘿嘿同学告诉我的,嘿嘿嘿太强了。