类欧几里得算法

当我们要计算形如

[ sum_{i=0}^nlfloor frac{ai+b}{c} floor ]

且a,b>=0,c>0时
可以使用类欧算法。

首先有以下公式

[lceil frac{a}{b} ceil = lfloor frac{a+b-1}{b} floor ]

[lfloorfrac{a}{b} floor = lceil frac{a-b+1}{b} ceil ]

挺容易推的:关于1式,如果 a % b != 0,那么右边就会比左边大1,2式原理相同。

然后开始推(?
我们令

[F(a,b,c,n)=sum_{i=0}^nlfloor frac{ai+b}{c} floor ]

[{a}geq{c}Rightarrowsum_{i=0}^nlfloor frac{ai+b}{c} floor=sum_{i=0}^n(lfloor frac{a\%c imes i+b}{c} floor+lfloorfrac{a}{c} floor i)=sum_{i=0}^nlfloor frac{a\%c imes i+b}{c} floor+lfloorfrac{a}{c} floorfrac{n imes (n+1)}{2} ]

[{b}geq{c}Rightarrowsum_{i=0}^nlfloor frac{ai+b}{c} floor=sum_{i=0}^nlfloor frac{a i+b\% c}{c} floor+lfloorfrac{b}{c} floor(n+1) ]

因此

[{a}geq{c}||{b}geq{c}Rightarrowsum_{i=0}^nlfloor frac{ai+b}{c} floor=sum_{i=0}^nlfloor frac{(a\%c) i+b\% c}{c} floor+lfloorfrac{b}{c} floor(n+1)+lfloorfrac{a}{c} floorfrac{n imes (n+1)}{2} ]

[Rightarrow F(a,b,c,n) = F(a\%c,b\%c,c,n)++lfloorfrac{b}{c} floor(n+1)+lfloorfrac{a}{c} floorfrac{n imes (n+1)}{2} ]

之后只要解决(a lt c && blt c)的情况就好了(?

[sum_{i=0}^nlfloor frac{ai+b}{c} floor =sum_{i=0}^nsum_{j=1}^{lfloor frac{ai+b}{c} floor}1 =sum_{i=0}^nsum_{j=1}^{lfloor frac{an+b}{c} floor}[{jleq lfloor frac{ai+b}{c} floor}] ]

交换求和顺序(

[Rightarrow sum_{j=1}^{lfloor frac{an+b}{c} floor}sum_{i=0}^n[{jleq lfloor frac{ai+b}{c} floor}] ]

又有

[lfloor frac{a}{b} floor geq c Leftrightarrow ageq bc ]

[lceil frac{a}{b} ceil leq c Leftrightarrow aleq bc ]

因此

[=sum_{j=1}^{lfloor frac{an+b}{c} floor}sum_{i=0}^n[jcleq {ai+b}] =sum_{j=1}^{lfloor frac{an+b}{c} floor}sum_{i=0}^n[lceil frac{jc-b}{a} ceil leq i] =sum_{j=1}^{lfloor frac{an+b}{c} floor}[n+1-lceil frac{jc-b}{a} ceil] ]

[=sum_{j=1}^{lfloor frac{an+b}{c} floor}[n+1-lfloor frac{jc-b+a-1}{a} floor] ]

[=nlfloor frac{an+b}{c} floor-sum_{j=1}^{lfloor frac{an+b}{c} floor}[lfloor frac{jc-b+a-1}{a} floor-1] =nlfloor frac{an+b}{c} floor-sum_{j=0}^{lfloor frac{an+b}{c} floor-1}[lfloor frac{(j+1)c-b-1}{a} floor] ]

因此我们有(a,blt c)

[F(a,b,c,n)=nlfloor frac{an+b}{c} floor-F(c,-1-b+c,a,lfloor frac{an+b}{c} floor-1) ]

然后就 可以递归了 终止条件a=0
以下代码

  ll exgcd(ll a, ll b, ll c, ll n){
        if(a==0) return (n+1)*(b/c);
        if(a>=c||b>=c) return exgcd(a%c, b%c, c, n) + floor(a/c)*n*(n+1)/2 + floor(b/c)*(n+1);
        ll temp = (a*n+b)/c;
        return n*temp - exgcd(c, c-b-1, a, temp-1);
  }
K-ON!!
原文地址:https://www.cnblogs.com/pophirasawa/p/12941304.html