稀疏表:最大公约数

news2024/11/19 5:45: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 math

def 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] = a
    for j in range(1, exp + 1):
        for start in range(1, arr_len + 1):
            if start + (1 << j) - 1 > arr_len:
                break
            dp[start][j] = gcd(dp[start][j - 1], dp[start + (1 << (j - 1))][j - 1])
    return dp

def 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 ** 9
        for i in range(1, n):
            l, r = i, n
            while l < r:
                mid = (l + r) >> 1
                if rmq_ask(dp, i, mid) == 1:
                    r = mid
                else:
                    l = mid + 1
            if rmq_ask(dp, i, r) == 1:
                ans = min(ans, r-i)
        print(ans + n-1)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/681440.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MIT 6.S081 教材第五章内容 -- 中断与设备驱动--下

MIT 6.S081 教材第五章内容 -- 中断与设备驱动--下 引言关于RISC-V特权级架构说明RISC-V特权模式OpenSBI介绍RISC-V启动过程RISC-V中的异常M模式下的异常1. 硬件中断的处理&#xff08;以时钟中断为例&#xff09;2. M模式下的异常相关寄存器3. 同步异常的处理 S模式下的异常1.…

chatgpt赋能python:Python散点图介绍:如何用Python绘制散点图?

Python散点图介绍&#xff1a;如何用Python绘制散点图&#xff1f; Python是一门流行的编程语言&#xff0c;用于解决各种问题和编写各种应用程序。其中&#xff0c;数据可视化是Python应用程序中非常重要的组成部分。散点图是最常用的数据可视化图形之一&#xff0c;它能够清…

拓扑排序:神经网络

题目链接 神经网络 题目大意 在兰兰的模型中&#xff0c;神经网络就是一张有向图&#xff0c;图中的节点称为神经元&#xff0c;而且两个神经 元之间至多有一条边相连&#xff0c;下图是一个神经元的例子&#xff1a; 图中&#xff0c; X 1 — X 3 X_1—X_3 X1​—X3​是信…

从类加载到双亲委派:深入解析类加载机制与 ClassLoader

目录 前言Class 文件介绍如何生成 class 文件观察 Bytecode 方法class 文件到底是什么样的呢&#xff1f; Class 加载、链接、初始化加载、类加载器双亲委派Launcher 核心类ClassLoader 相关源码ClassLoader 相关问题自定义简单 ClassLoader自定义加密 ClassLoader打破双亲委派…

动态ip与静态ip的概念、区别、应用场景

动态ip与静态ip的区别 前言一、介绍IP地址的概念和作用1.1、IP地址的定义1.2、IP地址的作用 二、动态IP和静态IP的区别2.1、动态IP和静态IP的定义2.2、动态IP和静态IP的特点2.3、动态IP和静态IP的优缺点比较 三、动态IP和静态IP的应用场景3.1. 动态IP的应用场景3.2. 静态IP的应…

利用numpy解决解方程组的基本问题

1 问题 进入大学&#xff0c;我们接触了线性代数&#xff0c;利用线性代数解方程组比高中慢慢计算会好了许多&#xff0c;快捷许多&#xff0c;我们作为编程人员&#xff0c;有没有用python解决解方程组的办法呢&#xff1f; 2 方法 我们提出使用python的numpy解方程。 找到用于…

11- C程序的组成结构 (C语言)

一、C程序的基本组成结构 1、源文件: 后缀为.c 的文件2、头文件&#xff1a;后缀为.h的文件 注意&#xff1a; 源文件 功能&#xff1a;实现程序功能头文件 功能&#xff1a;函数的声明、全局变量的声明、宏定义、类型的声明一个由C语言所组成的项目中 只允许有一个main函数 …

离散数学大作业任务书

目 录 实际的练习题目、系统的总功能和各子模块的功能………………………………………………………………………………1 1.1题目及问题描述………………………………………………………………1 1.2功能概述………………………………………………………………………1 1.3技…

02 | 日志系统:一条SQL更新语句是如何执行的?

以下内容出自《MySQL 实战 45 讲》 02 | 日志系统&#xff1a;一条SQL更新语句是如何执行的&#xff1f; 查询语句的那套流程&#xff0c;更新语句也会走一遍。 更新流程中和查询不一样的是&#xff0c;更新流程中涉及了两个重要的日志模块。redo log (重做日志) 和 binglog&a…

如何编写用于Neo-Hookean材料的Abaqus VUMAT Fortran子例程

引言 大家好&#xff0c;我是一个热爱编程、研究有限元分析的普通程序员。我非常感谢你们能够抽出宝贵的时间来阅读我的文章&#xff0c;你们的支持是我前行的动力。今天&#xff0c;我们将讨论一个非常专业的话题&#xff0c;即如何编写用于Neo-Hookean材料的Abaqus VUMAT Fo…

Unreal 5 实现UI制作

这一篇讲解一下unreal engine里面的内置ui插件UMG&#xff0c;虚幻示意图形界面设计器&#xff08;Unreal Motion Graphics UI Designer&#xff09;(UMG) 是虚幻引擎内置的一套ui制作工具&#xff0c;通过它我们能够实现平面ui&#xff0c;场景hud内容 实现背景图片填充整个…

【MySQL数据管理】:插入、修改、删除操作

前言 ✨欢迎来到小K的MySQL专栏&#xff0c;本节将为大家带来MySQL数据插入、修改、删除的讲解✨ 目录 前言一、插入数据二、修改数据三、删除数据四、总结 一、插入数据 使用INSERT INTO语句来向表中插入数据 ✨语法&#xff1a; 给指定字段添加数据 INSERT INTO 表名 (字段…

ctfshow web入门 php特性web98-102

1.web98 get会被post方式覆盖&#xff0c;传入的参数需要等于flag&#xff0c;才能读取到flag值,如果直接传http_flagflag,返回的结果会是一个空数组&#xff0c;因为get变量被覆盖了&#xff0c;而post没有传参 payload: get 11 post HTTP_FLAGflag 2.web99 array_push在数组…

机器视觉初步8:特征提取专题

文章目录 1.角点检测2.纹理特征提取3.特征描述符匹配3.1 Harris角点描述符3.2 SIFT&#xff08;尺度不变特征变换&#xff09;描述符3.3 SURF&#xff08;加速稳健特征&#xff09;描述符 4.基于深度学习的特征提取 在机器视觉中&#xff0c;特征提取是从目标图像中提取有用的视…

C语言:打印菱形(输入菱形上半部分行数)

题目&#xff1a; 用C语言在屏幕上输入以下图案&#xff1a; 思路&#xff1a; 总体思路&#xff1a; &#xff08;一&#xff09;. 输入菱形上半部分行数 -- scanf()函数 &#xff08;二&#xff09;. 使用 for循环 进行 菱形上半部分三角形 的打印&#xff0c; 菱形上半部分…

基于5G网络的视频远程操控应用实践——低延迟视频技术及应用

本次分享将分为三个部分&#xff1a;第一部分介绍低延迟视频所涉及到的关键技术&#xff0c;包括低延迟视频编解码、视频传输、视频处理低延时框架、视频采集和显示&#xff1b;第二部分重点介绍5G环境下低延迟视频对抗弱网提出的要求&#xff0c;包括&#xff1a;弱网状态的探…

Vulcanexus-一体化ROS2工具集

Vulcanexus机器人操作系统ROS2一站式工具集&#xff08;GalacticHumble&#xff09;2022 Humble Hierro v2 x86_64 arm64 Ubuntu Jammy (22.04) Vulcanexus是ROS 2的一站式工具集&#xff0c;用于构建机器人应用程序。它固定了DDS中间件&#xff0c;使用了Fast DDS&#xff…

word文件未保存 如何恢复

问题 word文件未保存 如何恢复 详细问题 笔者关闭已编辑完成的word文件&#xff0c;误触不保存&#xff0c;再次打开文件恢复至编辑前的状态&#xff0c;如何恢复至编辑完成后的状态 解决方案 文件 → \rightarrow →打开 → \rightarrow →恢复未保存的文件 或 1、打开 …

Spring关于@Configuration配置处理流程解析

Configuration配置处理流程解析 AnnotationConfigApplicationContext基于注解配置ApplicationContext启动刷新流程Spring关于Configuration解析处理流程那些年被忽略问题 AnnotationConfigApplicationContext基于注解配置 Spring通过上下文应用AnnotationConfigApplicationCon…

10- c语言复合数据类型 (C语言)

一 结构体 1.1 引入 1、在自然界中 任何一个物体&#xff0c;都有多个属性&#xff0c;如果用计算机语言来描述的话&#xff0c;一个属性也许可以用某一个基本数据类型来表示&#xff0c;但是当有多个属性的时候&#xff0c;一个基本数据类型就不能表示了。例如&#xff1a;学…