1. 程式人生 > >類歐幾裏得算法淺談(部分)

類歐幾裏得算法淺談(部分)

直線 過去 定義域 大於等於 畫出 一條直線 bcd abcd 取整

學習類歐幾裏得算法,因為是蒟蒻,感覺網上很多都看不懂,所以自己寫一篇快活快活


第一類求和式:

\(F(a,b,c,n)=\sum_{i=0}^n\lfloor\frac{a*i+b}{c}\rfloor\)


對於這樣形式的求和,我們有以下的推導:

1.當\(a>=c\)並且\(b>=c\)時,我們有:

對於\(\lfloor\frac{a}{c}\rfloor\),

它實際等價於\(\lfloor\frac{a\mod c}{c}\rfloor+\lfloor\frac{a}{c}\rfloor\),

於是對於原先的式子,我們可以推出:

\(F(a,b,c,d,n)=\sum_{i=0}^n\lfloor\frac{a*i+b}{c}\rfloor\)
=\(\sum_{i=0}^n(\lfloor\frac{a\mod c*i+b\mod c}{c}\rfloor+\lfloor\frac{a*i}{c}\rfloor+\lfloor\frac{b}{c}\rfloor)\)

進一步化為遞歸的形式就是:

\(F(a\%c,b\%c,c,n)+\frac{(n+1)n}{2}*\lfloor\frac{a}{c}\rfloor+(n+1)*\lfloor\frac{b}{c}\rfloor\)

2.當\(a<c\)或者\(b<c\)時我們有:

我們觀察可以很容易的發現,原先的和式的右邊一大堆,去掉下取整實際上表示出來就是一條直線,即:

\(F=kx+b\),(\(k=\frac{a}{c},b=\frac{b}{c})\),

然後我們就可以輕輕松松的畫出一個一次函數的圖像,在坐標系裏表現出的就是一個直角梯形,函數的定義域\(D\in[0,n]\),函數的值域\(Z\in[b,m]\),其中令\(m=\frac{a*n+b}{c}\),也就是當\(i\)等於\(n\)時的值.我們要求定義域內函數值的和,自然就是求積分,也就是這個直角梯形的面積.然後加上下整除符號,我們需要求出的就是這個梯形內整點的個數.

我們枚舉所有整點的縱坐標,就有:

\(F=\sum_{i=0}{n}\sum_{j=1}{m}[\lfloor\frac{a*i+b}{c}\rfloor>=j]\)

\(=\sum_{i=0}{n}\sum_{j=0}{m-1}[\lfloor\frac{a*i+b}{c}\rfloor>=j+1]\)

對於\([\lfloor\frac{a*i+b}{c}\rfloor>=j+1]\),我們知道,大於等於去掉下整除依舊成立,於是

\(=\sum_{i=0}^{n}\sum_{j=0}^{m-1}[(\frac{a*i+b}{c})>=j+1]\)

將分母乘過去,\(b\)移過去:

\(=\sum_{i=0}^{n}\sum_{j=0}^{m-1}[a*i>=j*c+c-b]\)

\(a\)除過去:

\(=\sum_{i=0}^{n}\sum_{j=0}^{m-1}[i>=\frac{(j*c+c-b)}{a}]\)

我們註意到,\(j\)的變化與\(i\)是無關的,於是我們可以將兩個\(\sum\)交換

\(=\sum_{j=0}^{m-1}\sum_{i=0}^{n}[i>=\frac{(j*c+c-b)}{a}]\)

\(=\sum_{j=0}^{m-1}\sum_{i=0}^{n}[i>\frac{(j*c+c-b-1)}{a}]\)

(分子減一,去掉等號)

去掉內層\(sigma\):

\(=\sum_{j=0}^{m-1} n-\frac{(j*c+c-b-1)}{a}\)

(這個顯然等價)

\(=n*m-\sum_{j=0}^{m-1} \frac{(j*c+c-b-1)}{a}\)

老規矩,轉換成遞歸形式:

\(=n*m-F(c,c-b-1,a,m-1)\)

(完)


(待補)

類歐幾裏得算法淺談(部分)