类欧几里得算法推导
类欧几里得算法推导
一般形式:\(f(a,b,c,n)=∑{_{i=0}^{n}}⌊(ai+b)/c⌋\)
设:\(a=x_1c+y_1,b=x_2c+y_2\)
那么
\(⌊(ai+b)/c⌋\)
\(=⌊((x_1c+y_1)i+(x_2c+y_2))/c⌋\)
\(=⌊(y_1i+y_2)/c⌋+x_1*i+x_2⌋\)
\(=⌊(y_1i+y_2)/c⌋+x_1*i+x_2\)
那么原式就有:
\(f(a,b,c,n)\)
\(=∑{_{i=0}^{n}}⌊(ai+b)/c⌋\)
\(=∑{_{i=0}^{n}}(⌊(y_1i+y_2)/c⌋+x_1*i+x_2)\)
\(=∑{_{i=0}^{n}}⌊(y_1i+y_2)/c⌋+∑{_{i=0}^{n}}x_1*i+∑{_{i=0}^{n}}x_2\)
\(=∑{_{i=0}^{n}}⌊((y_1i+y_2))/c⌋+x_1*(n+1)*n/2+x_2*(n+1)\)
那么就转为求\(∑{_{i=0}^{n}}⌊((y_1i+y_2))/c⌋\)的值。
其实很容易发现:\(∑{_{i=0}^{n}}⌊(y_1i+y_2)/c⌋\)和最初的式子\(∑{_{i=0}^{n}}⌊(ai+b)/c⌋\)是一个样子,那么为什么要进行这一步转换呢?
由\(a=x_1c+y_1,b=x_2c+y_2\)可知,\(y_1<=a,y_2<=b\),进一步可知\(y_1*i+y2<=a*i+b\),所以\(⌊(y_1i+y_2)/c⌋<=⌊(ai+b)/c⌋\)。
设\(up1=⌊(y_1n+y_2)/c⌋,up2=⌊(an+b)/c⌋\),\(up\)代表取值上界。
当\(a,b>c\)时,\(up2\)到\(up1\)的转换可以大大缩小取值上界。
缩小取值上界的作用将在后文进行讲解。
假设:\(f(i)=(y_1i+y_2)/c\)的图像如下
那么加上下取整之后的图像为:
首先从几何角度来讲,一个点\((a,b)\)的下取整表示在\(x=a\)这条线上满足\(y>0,y<=b,\)且\(y\)是整数的点的个数。
那么就可以通过枚举\(x\)或者\(y\)得到所有绿色横线上的值,那么就有新的问题了,即哪种枚举时间复杂度最优。
\(n-up1\)
\(>=n-((y_1*n+y_2)/c)\)
\(=1/c(nc-y_1n-y_2)\)
\(=1/c(n(c-y1)-y2)\)
由于\(c-y1>0\)且大多题目有\(n>>c>y_2\),所以本式最终结果大于0,即得证\(n>up1\),枚举\(y\)坐标的次数一定小于枚举\(x\)坐标的次数。
利用容斥可以得到一种算法。
对于每个\(y\)找\(f(i)<y\)的个数,然后用\(n*m\)减去这部分。
如果枚举合法状态的话,下界为\(⌊y_2/c⌋=0\),所以枚举\(y\)一定是从\(0\)枚举到\(up1\)\()\)
那么一定不存在\(f(i)<y\)的点,那么就从\(1\)枚举到\(up1\)
\((ai+b)/c<y\)移项得到\(i<(cy-b)/a\),\(i\)取整数,\((cy-b-1)/a\)可以保证当\((cy-b)/a\)为整数的时候,经过这个转换,再下取整,可以得到一个合法边界。
所以\(sum=n*up-∑{_{y=1}^{up}}(cy-b-1)/a=n*up-∑{_{y=0}^{up-1}(cy+c-b-1)/a}\)
\(∑{_{y=0}^{up-1}(cy+c-b-1)/a}=f(c,c-b+1,a,up-1)\)
前面的mod处理也是为了这里下放的\(c-b+1>0\)
所以就得到整体的递推式:
ll calc(ll a, ll b, ll c, ll n)
{
if (!a) return b / c * (n + 1);
if (a < c && b < c)
{
ll m = (a * n + b) / c;
if (!m) return 0;
return n * m - calc(c, c - b - 1, a, m - 1);
}
return calc(a % c, b % c, c, n) + n * (n + 1)/2 * (a / c) + (n + 1) * (b / c);
}

浙公网安备 33010602011771号