📜  范围LCM查询(1)

📅  最后修改于: 2023-12-03 15:27:47.051000             🧑  作者: Mango

范围LCM查询

在数学和计算机科学中,最小公倍数(LCM)是指两个或多个整数的公共倍数中最小的那个数。在某些算法中,需要计算一段连续整数范围内的最小公倍数,这就是范围LCM查询。

实现方法

范围LCM查询可以通过线段树实现。我们可以使用线段树来维护每个区间的LCM,从而实现查询。

具体实现过程如下:

  1. 在每个节点上维护一个最小公倍数的值LCM。
  2. 在建立线段树的过程中,将每个叶子节点的LCM初始化为该节点所代表的值。
  3. 对于任意区间[l, r],其最小公倍数LCM[l, r]等于LCM[左儿子]和LCM[右儿子]的最小公倍数。
  4. 对于每次的查询操作,可以通过深度优先遍历线段树,在碰到区间[l, r]与查询区间[qL, qR]相交的节点时更新答案。
代码实现

下面是使用Python实现的范围LCM查询代码:

class SegmentTree:
    def __init__(self, n: int):
        self.tree = [(0, 0)] * (n * 4)
        self.build(1, 1, n)

    def build(self, idx: int, l: int, r: int) -> None:
        if l == r:
            self.tree[idx] = (l, l)
            return

        mid = (l + r) // 2
        self.build(idx * 2, l, mid)
        self.build(idx * 2 + 1, mid + 1, r)

        self.tree[idx] = self.merge(self.tree[idx * 2], self.tree[idx * 2 + 1])

    def query(self, idx: int, l: int, r: int, ql: int, qr: int) -> int:
        if l > qr or r < ql:
            return 1

        if ql <= l and qr >= r:
            return self.tree[idx][1]

        mid = (l + r) // 2
        left = self.query(idx * 2, l, mid, ql, qr)
        right = self.query(idx * 2 + 1, mid + 1, r, ql, qr)

        return self.merge((left, ql), (right, qr))[1]

    def merge(self, a, b):
        if a[0] == 0:
            return b
        if b[0] == 0:
            return a

        lcm_ab = LCM(a[0], b[0])
        argmin = a[1] if lcm_ab % a[0] == 0 else b[1]
        return (lcm_ab, argmin)


def LCM(a: int, b: int) -> int:
    return a * b // GCD(a, b)


def GCD(a: int, b: int) -> int:
    if a == 0:
        return b
    return GCD(b % a, a)
总结

范围LCM查询是一道有趣的问题,它的解法涉及线段树、最小公倍数、最大公约数等多种基本算法和数据结构。在实际应用中,我们可以使用这一技巧来解决一系列涉及到区间LCM的问题。