数列GCD

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数列GCD相关的知识,希望对你有一定的参考价值。

数列 GCD

  数列的 GCD 具有一些很迷人的性质, 值得我用一个完整的页面阐述.

 

  一般地, GCD 具有可并性: 设有互不相交的多重集合 S, T , 则 $gcd(S \cup T) = gcd(gcd(S), gcd(T))$ .

  如果我们给定一个数列 $A$ , 要求某个区间的 gcd , 那么就可以使用线段树, ST 表等区间合并的结构, 在 $O(\log n)$ 或 $O(\log ^ 2 n)$ 求解.

 

  数列的 GCD 还具备更多的性质.

  为了方便阐述, 设 $S_{l, r} = gcd(a_l, a_{l+1}, ..., a_r)$ .

  当 $l$ 一定时, 可以将 $S_{l, r}$ 看作一个 $r$ 的函数, 它具有怎么样的性质?

  1. 随着 $r$ 的增大, $S_{l, r+1}$ 单调不上升, 前一个数一定是后一个数的倍数.

  2. $S_{l, r}$ 的取值个数的上限为 $O(\log n)$ , 因为若 $S_{l, r} \ne S_{l, r+1}$ , 那么 $S_{l, r} \ge 2 S_{l, r+1}$ , 所以序列的所有区间的不同 GCD 个数为 $O(n \log n)$ .

  

  如何对所有 $l$ , 求出所有 GCD 不同的 r 的集合 $R_l$ , 即对于 $r \in R_l$ , $S_{l, r} \ne S_{l, r-1}$ .

  我们考虑利用连续性高效处理, 得到 $O(\log ^ 2 n)$ 的做法.

  考虑由 $R_{l+1}$ , 求出 $R_l$ . 由 GCD 的可并性可证明若 $S_{l+1, p} = S_{l+1, q}$ , 那么 $S_{l, p} = S_{l, q}$ . 所以 $R_{l}$ 一定是 $R_{l+1}$ 的子集并上 $\left\{ l \right\}$ . 我们直接将 $R_{l+1}$ 中的所有元素对应的 GCD 进行更新和去重, 即可得到 $R_l$ .

  实现如下:

 1     static pair<int, int> tmp[S];
 2     int tot = 0;
 3      
 4     tmp[++tot] = make_pair(pos, w);
 5     F(i, 1, Len) {
 6         int g = gcd(w, Lis[i].second);
 7         if (g != tmp[tot].second)
 8             tmp[++tot] = make_pair(Lis[i].first, g);
 9     }
10      
11     memcpy(Lis, tmp, sizeof tmp);
12     Len = tot;

 

 

 

[HDU 5869] Different GCD Subarray Query

  题意

  给定序列 $A$ , 多次询问某个区间的所有子区间的不同 GCD 个数.

  分析

  离线处理.

  维护 $R_l$ 的同时, 把 $R_l$ 产生的 GCD 对每个右端点进行贡献.

  如果之前已经贡献过当前这种 GCD , 那么先清楚掉之前的贡献.

 

1     F(i, 1, Len) {
2         if (Last[Lis[i].second] > 0)
3             add(Last[Lis[i].second], -1);
4         add(Last[Lis[i].second] = Lis[i].first, +1);
5     }

 

 

 

以上是关于数列GCD的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ 4305 4305: 数列的GCD (数论)

bzoj4305 数列的GCD

fibonacci数列的性质和实现方法

PTA乙级 (1049 数列的片段和 (20分))

[乱搞]斐波那契数列与gcd之间一个有趣的定理

LQ0004 等差数列GCD