类欧几里得算法学习笔记
其实我也不知道这个算法的英文名是啥(
我就 yy 出来一个「Similar Euclid Algorithm」(
给你六个非负整数 $n,a,b,c,k_{1},k_{2}$,你需要求出
$n,a,b,c\leqslant 10^{9}$,$k_{1}+k_{2}\leqslant 10$。
太难了,告辞(
所以我们现在来研究简单一点的。
给你四个非负整数 $n,a,b,c$,你需要求出
$n,a,b,c\leqslant 10^{9}$,$10^{5}$ 组询问。
于是我们开始愉快地推式子。首先我们暂不考虑取模,也就是下文中先用等号代替同余。
首先考虑 $f(n,a,b,c)$,假设 $a\geqslant c\vee b\geqslant c$
也就是说,我们只需要重点关注 $a\lt c\wedge b\lt c$ 时的情况即可。我们令 $m=\lfloor\cfrac{an+b}{c}\rfloor$,然后继续往下推
然后我们发现,我们可能需要在 $\cfrac{cj+c-b}{a}$ 周围来一个上取整,然而上取整并没有什么比较好的性质。
考虑转换一下思路。既然 $cj+c\leqslant ai+b$,我们就有 $cj+c\lt ai+b+1$,然后再往下
然后我们看到,这个函数它递归了!
注意到 $(a,b,c)$ 变成了 $(c,c-b-1,a)$,虽然我不是很能理解,反正这个东西最多递归 $\log a$ 次,时间复杂度就是 $O(\log a)$ 了。
然后考虑 $g(n,a,b,c)$。
$a\geqslant c\vee b\geqslant c$:
$a\lt c\wedge b\lt c$,当然 $m$ 还是 $\lfloor\cfrac{an+b}{c}\rfloor$:
我们可以把上面这个式子理解成 $\gt\lfloor\cfrac{cj+c-b-1}{a}\rfloor$ 且 $\leqslant n$ 的所有自然数之和,于是差分一下我们得到
我们看到这个函数调用了 $h(n,a,b,c)$,我们接下来就来研究一下这个函数。
$a\geqslant c\vee b\geqslant c$:
您绝对想象不到上面这一坨子东西的 $\TeX$ 源码长什么样(
$a\lt c\wedge b\lt c$:
然后我们发现推不下去了。
不过办法总是有的。首先我们有一个看起来没啥用的式子
套进去
然后我们看到它奇迹般地递归了!
我们来总结一下。
但是还有一个细节,如果说 $n=0$ 或 $a=0$,我们需要直接特判,大概像这样:
另外写的时候注意三个函数值要套在结构体里一起算,不然还是会 T。
1 |
|
那么问题来了,这个东西有什么用啊。
没啥用(
其他的模板题我就不举了,我们来看一下这样一道题。
看到推平操作我们可以直接往珂朵莉树上想了。
那么对于被推平的一段区间,我们将其压成一个节点丢到珂朵莉树上,然后维护六个信息 l,r,L,R,a,b
,表示其对应原序列中的 $[l,r]$ 这段区间,里面一共有 $\sum_{i=L}^{R}ai\operatorname{mod}b$ 颗石头。注意这里的 l,r,L,R
一定不要搞混,我就是因为这样 WA 了整整四遍(。
这三个样例一定是故意的。
然后每次我们初始化一个节点的时候直接算出节点内的石头总数,像下面这样:
直接一波板子套上去。
还有就是,这么算的话中间量会爆 long long
,我们可以考虑用 __int128_t
来存。不过这个类型在本地一般是编译不了的,虽然说交到 OJ 上基本没问题。我们可以
1 |
然后把一些没必要用或者是不能用 __int128_t
的改成 signed
即可。
代码还是有必要贴一下的。
1 |
|