稀疏表:最大公约数

news/2025/2/23 1:08:30/

问题描述

给定一个数组, 每次操作可以选择数组中任意两个相邻的元素 x , y x, y x,y 并将其 中的一个元素替换为 gcd ⁡ ( x , y ) \operatorname{gcd}(x, y) gcd(x,y), 其中 gcd ⁡ ( x , y ) \operatorname{gcd}(x, y) gcd(x,y) 表示 x x x y y y 的最大公约数。 请问最少需要多少次操作才能让整个数组只含 1 。

解题思路

关于 g c d gcd gcd
如果一段子数组的的 g c d gcd gcd 1 1 1,那么原数组的 g c d gcd gcd也一定为 1 1 1
如果存在一个子数组的 g c d gcd gcd 1 1 1,那么这个数组无论再加上任何正整数, g c d gcd gcd也永远是 1 1 1因为 1 1 1和任何数的 g c d gcd gcd都是 1 1 1

1、(简单)考虑数组中是否存在 1 1 1,如果数组中存在 1 1 1,依次把全部元素变成 1 1 1,假设 1 1 1的个数为 x x x个,那么最终的答案是 n − x n-x nx次。
复杂——原数组中不存在 1 1 1
2、变出一个 1 1 1,然后使用这个 1 1 1进行平推将数组全部变成 1 1 1
3、 [ 1 , n ] [1,n] [1,n] g c d gcd gcd都不为 1 1 1,那么任何子数组的 g c d gcd gcd也不可能为 1 1 1,此时为无解。
问题——如何最少次数变出 1 1 1
任务转换——原数组中找到最短的子数组,使得它们的 g c d gcd gcd为1。

如果 [ l , r ] [l,r] [l,r] g c d gcd gcd 1 1 1
1、那么 [ l , r + 1 ] . . . [ l , n ] [l,r+1]...[l,n] [l,r+1]...[l,n]这些区间的 g c d gcd gcd也一定为 1 1 1
2、而 [ l , l + 1 ] . . . [ l , r − 1 ] [l,l+1]...[l,r-1] [l,l+1]...[l,r1]这些区间却并不一定符合条件。
二分法。对于数组中的每个数我们固定为左端点 l l l,然后去二分右端点,求出使得 区间 [ l , r ] 区间[l,r] 区间[l,r] g c d gcd gcd 1 1 1最小的右端点。这样每个数我们都定为左端点去二分它的右端点,所有答案取最小值就能找出 g c d gcd gcd 1 1 1的最短区间。

注意:Python语言运行较慢,推荐写成st表,不推荐写线段树,线段树常数太大。
时间复杂度 O ( n l o g n ) O(nlogn) O(nlogn)
ST算法是基于倍增思想设计的在线算法,记录从每个元素开始的连续长度为 2 k 2^k 2k的区间中元素的GCD。
预处理
类似于动态规划,规定 d p [ i ] [ j ] dp[i][j] dp[i][j]表示从第 i i i 个元素起连续 2 i 2^i 2i个数中的GCD,即记录中的最大公约数。
d p [ i ] [ j ] dp[i][j] dp[i][j]代表的区间 [ i , i + 2 j − 1 ] [i,i+2^j-1] [i,i+2j1]的最大公约数,而区间 [ i , i + 2 j − 1 ] [i,i+2^j-1] [i,i+2j1]上包含偶数个数字,故把 [ i , i + 2 j − 1 ] [i,i+2^j-1] [i,i+2j1]平均分成两段,从 i i i i + 2 j − 1 − 1 i+2^{j-1}-1 i+2j11为一段, i + 2 j − 1 i+2^{j-1} i+2j1 i + 2 j − 1 i+2^j-1 i+2j1为另一段,长度均为 2 j − 1 2^{j-1} 2j1
d p [ i ] [ j ] = g c d ( d p [ i ] [ j − 1 ] , d p [ i + 2 j − 1 ] [ j − 1 ] ) dp[i][j]=gcd(dp[i][j−1],dp[i+2^{j−1}][j−1]) dp[i][j]=gcd(dp[i][j1],dp[i+2j1][j1])
蓝桥云课
查询
1、不允许重叠,区间的长度按照二进制分成多个 2 2 2的整数倍区间,这些区间是求多次最大公约数能得到答案。
2、允许区间重叠,所有的情况下最多只要两个区间要求区间 , [ l , r ] [l,r] [l,r]中的最大公约数,找到一个数 k k k 使得 2 k < r − l + 1 2^k <r−l+1 2k<rl+1,即 k = ⌊ log ⁡ 2 ( r − l + 1 ) ⌋ k = \lfloor \log_2(r-l+1) \rfloor k=log2(rl+1)⌋
可以把这个区间分成两个部分: [ l , l + 2 k − 1 ] [l, l+2^k-1] [l,l+2k1] [ r − 2 k + 1 , r ] [r-2^k+1, r] [r2k+1,r]
这两个区间恰好是刚刚已经初始化好的,前者对应的是 d p [ l ] [ k ] dp[l][k] dp[l][k],后者对应的是 d p [ r − 2 k + 1 ] [ k ] dp[r-2^k+1][k] dp[r2k+1][k]

Ac_code

python

# -*- coding: utf-8 -*-
# @Author : BYW-yuwei
# @Software: python3.8.6
from math import gcd
import mathdef rmq_init(arr):arr_len = len(arr)exp = int(math.log(arr_len, 2))dp = [[0] * (exp + 1) for _ in range(arr_len + 1)]for i, a in enumerate(arr):dp[i + 1][0] = afor j in range(1, exp + 1):for start in range(1, arr_len + 1):if start + (1 << j) - 1 > arr_len:breakdp[start][j] = gcd(dp[start][j - 1], dp[start + (1 << (j - 1))][j - 1])return dpdef rmq_ask(dp, left, right):  k = int(math.log(right - left + 1, 2))return gcd(dp[left][k], dp[right + 1 - (1 << k)][k])n = int(input())
a = list(map(int, input().split()))cnt1 = sum(ai == 1 for ai in a)
if cnt1 > 0:print(n - cnt1)
else:dp = rmq_init(a)if rmq_ask(dp, 1, n) != 1:print(-1)else:ans = 10 ** 9for i in range(1, n):l, r = i, nwhile l < r:mid = (l + r) >> 1if rmq_ask(dp, i, mid) == 1:r = midelse:l = mid + 1if rmq_ask(dp, i, r) == 1:ans = min(ans, r-i)print(ans + n-1)

http://www.ppmy.cn/news/559977.html

相关文章

Reqable HTTP一站式开发+调试工具(小黄鸟作者另一力作、小黄鸟完美替代品)

本文所有教程及源码、软件仅为技术研究。不涉及计算机信息系统功能的删除、修改、增加、干扰,更不会影响计算机信息系统的正常运行。不得将代码用于非法用途,如侵立删!Reqable HTTP一站式开发+调试工具(小黄鸟作者另一力作、小黄鸟替代品) 环境 win10pixel4Android13概览 …

清华大学镜像源地址

https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/win-64/

python设置清华源镜像

1、设置临时清华源镜像 pip install -i https://pypi.tuna.tsinghua.edu.cn/simple some-package2、设置默认永久清华源镜像 #升级 pip install pip -U #设置 pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple

清华源或中科大源下载速度慢

清华源&#xff1a; 可以用这个&#xff1a;https://mirror.tuna.tsinghua.edu.cn/&#xff0c;就是不要mirror后面的s 中科大源&#xff1a; https://mirrors.ustc.edu.cn/ 进去后可以选择域名&#xff0c;如果是校园网可以选择教育网线路&#xff0c;其它几个也可以试试&…

Ubuntu20.04换为清华的镜像源

安装过程&#xff1a; Ubuntu 的软件源配置文件是 /etc/apt/sources.list。 在修改之前&#xff0c;先将系统自带的该文件做个备份&#xff0c;将该文件替换为清华源官网提供的内容&#xff0c;即可使用 TUNA 的软件源镜像。 第一步&#xff1a; 切换到root账户&#xff1a…

【Python】pip配置清华镜像源

一、前言 在使用pip命令安装python的一些库时&#xff0c;由于默认服务器在国外&#xff0c;因此下载需要很长时间&#xff0c;这时我们可以修改默认配置&#xff0c;将服务器设置成国内的服务器&#xff0c;以可以大幅度提高下载速度&#xff0c;而清华镜像源就是其中之一。 …

centos8修改yum清华源

centos8修改yum清华源 1&#xff0c;首先进入/etc/yum.repos.d/目录下&#xff0c;新建一个repo_bak目录&#xff0c;用于保存系统中原来的repo文件** [rootGXY ~]# cd /etc/yum.repos.d/[rootbogon yum.repos.d]# mkdir repo_bak[rootbogon yum.repos.d]# mv *.repo repo_ba…

Debian配置清华源

确定debian的系统版本 plcdebian:~$ cat /etc/os-release PRETTY_NAME"Debian GNU/Linux 9 (stretch)" NAME"Debian GNU/Linux" VERSION_ID"9" VERSION"9 (stretch)" VERSION_CODENAMEstretch IDdebian HOME_URL"https://www.de…