题目描述

对于两个正整数 a,ba,ba,b,他们的最大公因数记为 gcd⁡(a,b)\gcd(a,b)gcd(a,b)。对于 k>3k > 3k>3 个正整数 c1,c2,…,ckc_1,c_2,\dots,c_kc1,c2,,ck,他们的最大公因数为:

gcd⁡(c1,c2,…,ck)=gcd⁡(gcd⁡(c1,c2,…,ck−1),ck)\gcd(c_1,c_2,\dots,c_k)=\gcd(\gcd(c_1,c_2,\dots,c_{k-1}),c_k)gcd(c1,c2,,ck)=gcd(gcd(c1,c2,,ck1),ck)

给定 nnn 个正整数 a1,a2,…,ana_1,a_2,\dots,a_na1,a2,,an 以及 qqq 组询问。对于第 i(1≤i≤q)i(1 \le i \le q)i(1iq) 组询问,请求出 a1+i,a2+i,…,an+ia_1+i,a_2+i,\dots,a_n+ia1+i,a2+i,,an+i 的最大公因数,也即 gcd⁡(a1+i,a2+i,…,an+i)\gcd(a_1+i,a_2+i,\dots,a_n+i)gcd(a1+i,a2+i,,an+i)

输入格式

第一行,两个正整数 n,qn,qn,q,分别表示给定正整数的数量,以及询问组数。

第二行,nnn 个正整数 a1,a2,…,ana_1,a_2,\dots,a_na1,a2,,an

输出格式

输出共 qqq 行,第 iii 行包含一个正整数,表示 a1+i,a2+i,…,an+ia_1+i,a_2+i,\dots,a_n+ia1+i,a2+i,,an+i 的最大公因数。

输入输出样例 #1

输入 #1

5 3
6 9 12 18 30

输出 #1

1
1
3

输入输出样例 #2

输入 #2

3 5
31 47 59

输出 #2

4
1
2
1
4

说明/提示

对于 60%60\%60% 的测试点,保证 1≤n≤1031 \le n \le 10^31n1031≤q≤101 \le q \le 101q10

对于所有测试点,保证 1≤n≤1051 \le n \le 10^51n1051≤q≤1051 \le q \le 10^51q1051≤ai≤10001 \le a_i \le 10001ai1000

提交链接

https://www.luogu.com.cn/problem/P13014

思路分析

🔍 暴力解法,适用于 60%60\%60% 数据

我们观察题目的形式,会发现每次查询是对整个数组加上一个偏移量 iii,然后再计算它们的最大公因数。这种问题在数据范围较小时,可以直接暴力解决。

1. 暴力模拟每个询问

  • 对于每次询问 iii,我们把数组中每个元素都加上 iii,得到一个新的数组。

  • 然后,我们对新数组依次计算 gcd

  • 由于 gcd 满足结合律,我们可以通过从前往后扫描数组,依次更新当前的 gcd 值。

例如,若有数组:

a = [6, 9, 12]
i = 1
则变为 [7, 10, 13]
然后计算 gcd(7, 10, 13)

实现方式:

  • 初始设 gcd=a[0]+igcd = a[0] + igcd=a[0]+i
  • 然后遍历其余元素:gcd=gcd⁡(gcd,a[j]+i)gcd = \gcd(gcd, a[j] + i)gcd=gcd(gcd,a[j]+i)

最终的 gcdgcdgcd 就是这一组询问的答案。

2. 算法复杂度分析

  • 外层:询问数量为 qqq
  • 内层:每次询问需要遍历 nnn 个元素
  • 总体复杂度为 O(q⋅n)O(q \cdot n)O(qn)

对于题目中说的 60%60\%60% 数据范围(n≤1000,q≤10n \le 1000, q \le 10n1000,q10),这个复杂度是可以接受的:1000×10=1041000 \times 10 = 10^41000×10=104gcdgcdgcd 计算。


参考代码

#include <bits/stdc++.h>
using namespace std;int main()
{int n, q;cin >> n >> q;   //n个数字  q次询问vector<int> a(n);for (int &i : a)cin >> i;for(int i = 1; i <= q; i++)  //q次询问{int gcd = a[0] + i;for(int j = 1; j < n; j++)gcd = __gcd(gcd , a[j] + i);cout << gcd << endl;}return 0;
}

✅ 解题思路(优化做法,适用于 100%100\%100% 数据)

🔍 问题本质转化

我们要计算每次查询:gcd(a₁ + i, a₂ + i, ..., aₙ + i)

qqq 次对 nnn 个数求 GCD,暴力做法时间复杂度是 O(q⋅n)O(q \cdot n)O(qn),显然会超时。但我们可以利用 GCD 的平移不变性结合律 优化这个过程。

🧠 核心数学性质

一个关键性质是:

  • gcd(x + a₁, x + a₂, ..., x + aₙ) = gcd(x + a₁, a₂ - a₁, a₃ - a₁, ..., aₙ - a₁)

也就是说,我们可以把所有的 ai+xa_i + xai+x 表达成:gcd(a₁ + x, d₂, d₃, ..., dₙ)

其中 di=ai−a1d_i = a_i - a₁di=aia1,即所有数与第一个数的差。

💡 为什么这个公式成立?

这个公式的核心原理来源于 GCD 的不变性GCD 对加减法的封闭性

对于任意整数 u,vu, vu,v,都有:gcd(u, v) = gcd(u, v - u)

这是我们在辗转相除法(欧几里得算法)中使用的基本规则。

🧠 用在这个问题里,我们怎么理解?

我们要求的是:g = gcd(x + a₁, x + a₂, ..., x + aₙ)

我们可以把所有的数都减去 (x+a1)(x + a₁)(x+a1),即:

(x + a₂) - (x + a₁) = a₂ - a₁  
(x + a₃) - (x + a₁) = a₃ - a₁  
...  
(x + aₙ) - (x + a₁) = aₙ - a₁

根据 gcdgcdgcd 的性质,这种减法不会改变最终的 gcdgcdgcd 结果。所以我们可以把上面的式子变形为:

  • gcd(x + a₁, a₂ - a₁, a₃ - a₁, ..., aₙ - a₁)

✅ 举个例子理解

假设:a = [6, 9, 12]

查询值:x = 1

我们要求:gcd(6 + 1, 9 + 1, 12 + 1) = gcd(7, 10, 13)

现在按照公式转换:

x + a₁ = 7  
差值:  
9 - 6 = 3  
12 - 6 = 6

转化为:gcd(7, 3, 6)

继续计算:

gcd(7, 3) = 1  
gcd(1, 6) = 1

结果是:111,与原始计算:gcd(7, 10, 13) 得到的结果一致。

⚙️ 实现方式

我们可以将这些差值的 GCD 预处理出来,代码如下:

int g = a[1] - a[0];
for (int i = 2; i < n; i++) {g = __gcd(g, abs(a[i] - a[0]));
}

然后每次查询只需要计算:

__gcd(a[0] + x, g);

这就将 O(q⋅n)O(q \cdot n)O(qn) 优化成了 O(n+qlog⁡A)O(n + q \log A)O(n+qlogA)

🔧 代码分析

差值 gcd 预处理

int g = a[1] - a[0];
for(int i = 2; i < n; i++) 
{g = __gcd(g , abs(a[i] - a[0]));
}

这段代码做的是:将所有差值的 gcdgcdgcd 预处理出来,时间复杂度 O(n)O(n)O(n)

查询处理:
for(int i = 1; i <= q; i++) {int gcd = __gcd(g , a[0] + i);cout << gcd << endl;
}

每次查询的时间复杂度是 O(log⁡A)O(\log A)O(logA)

📌 时间复杂度分析

  • 差值 gcdgcdgcd 预处理:O(n)O(n)O(n)
  • 每次查询:O(log⁡A)O(\log A)O(logA),总共 qqq 次,复杂度为 O(qlog⁡A)O(q \log A)O(qlogA)
  • 总体时间复杂度:O(n+qlog⁡A)O(n + q \log A)O(n+qlogA)

这个复杂度对于题目给定的最大范围 n,q≤105n, q \le 10^5n,q105 是完全可以接受的。

参考代码

#include <bits/stdc++.h>
using namespace std;int main()
{int n, q;cin >> n >> q; // n个数字  q次询问vector<int> a(n);for (int &i : a)cin >> i;int g = 0;for (auto it : a)g = __gcd(g, abs(it - a[0]));for (int i = 1; i <= q; i++) // q次询问{int gcd = __gcd(g, a[0] + i);cout << gcd << endl;}return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

实现一个进程池(精讲)

目录 写进程池前的理论扫盲 进程池的实现 写进程池前的理论扫盲 父进程创建子进程&#xff0c;父子俩都看见同一片资源&#xff0c;这片资源被俩进程利用&#xff0c;用来通信&#xff0c;这片资源就是管道&#xff0c;如图所示&#xff0c;能很好地诠释管道。 那么什么是进程…

【tips】css模仿矢量图透明背景

就像棋盘格background-image: linear-gradient(45deg, #f0f0f0 25%, transparent 25%), linear-gradient(-45deg, #f0f0f0 25%, transparent 25%), linear-gradient(45deg, transparent 75%, #f0f0f0 75%), linear-gradient(-45deg, transparent 75%, #f0f0f0 75%);background-…

visual studio 历史版本安装

visual studio 历史版本安装 链接&#xff1a;Visual Studio 版本路线图 说明&#xff1a;该页面提供历史版本的发布说明及下载链接&#xff08;需滚动至页面底部查找相关版本&#xff09;。例如&#xff0c;2022 版本可能包含 17.0 至 17.14 等子版本&#xff0c;用户可根据需…

微软推出“愤怒计划“:利用AI工具实现恶意软件自主分类

微软周二宣布推出一款能够自主分析并分类软件的人工智能&#xff08;AI&#xff09;代理系统&#xff0c;旨在提升恶意软件检测能力。这款基于大语言模型&#xff08;LLM&#xff09;的自主恶意软件分类系统目前仍处于原型阶段&#xff0c;被微软内部代号命名为"愤怒计划&…

SOLIDWORKS Electrical:实现真正意义上的机电协同设计

随着市场的发展&#xff0c;企业面临两个方面的挑战&#xff1a;从业务和市场方面来看&#xff0c;为了在竞争中取得更大优势&#xff0c;需要更高质量的产品&#xff0c;较低的成本并缩短产品上市周期&#xff1b;从设计和技术方面来看&#xff0c;产品的集成度越来越高&#…

MySql_忘记了root密码怎么办

《MySql_忘记了root密码怎么办》在忘记root密码的时候&#xff0c;可以按以下步骤处理&#xff08;以windows为例&#xff09;。_1) 关闭正在运行的MySQL服务。_2) 打开DOS窗口&#xff0c;转到mysql\bin目录。_3) 输入mysqld –skip-grant-tables 回车。–skip-grant-tables 的…

wstool和catkin_tools工具介绍

好的&#xff0c;我们来详细介绍一下 python3-wstool 和 python3-catkin-tools 这两个在 ROS (Robot Operating System) 开发中非常重要的工具&#xff0c;以及它们之间的关系。 首先&#xff0c;python3- 这个前缀表示这些是针对 Python 3 的软件包版本&#xff0c;这在现代 R…

吴恩达 深度学习笔记

最近在看吴恩达深度学习系列课程&#xff0c;简单做一个基本框架笔记。 如感兴趣或了解更多内容&#xff0c;推荐看原课程 以前也做过一些与机器学习和深度学习有关的笔记&#xff0c;过分重复的就一笔带过了。 01 第一门课 神经网络和深度学习 1.1 第一周&#xff1a;深度学习…

2025数字马力一面面经(社)

2025数字马力一面面经&#xff08;社&#xff09; 日常自我介绍js数据类型有哪些&#xff08;报完菜名后简单分析了一下使用引用类型&#xff09;谈谈对const、var、let的理解&#xff08;变量提升、let和const的主要区别、使用const命名引用类型的时可以对引用类型进行操作&am…

PyQt 中 pyqtSignal 的使用

目录 基本用法 示例代码 关键特性 常见用途 一、信号的定义规则 二、完整用法步骤 1. 导入必要模块 2. 定义带信号的类 3. 定义接收信号的槽函数 4. 连接信号与槽 5. 发射信号 6. 断开连接(可选) 三、高级特性 1. 跨线程通信 2. 信号连接方式 3. 信号与匿名函数 4. 信号转发 …

使用Python验证常见的50个正则表达式

什么是正则表达式&#xff1f;正则表达式&#xff08;Regular Expression&#xff09;通常被用来检索、替换那些符合某个模式(规则)的文本。此处的Regular即是规则、规律的意思&#xff0c;Regular Expression即“描述某种规则的表达式”之意。本文收集了一些常见的正则表达式用…

Redis是单线程性能还高的原因

Redis是单线程Redis单线程是指Redis的网络IO和键值对读写是由一个线程完成的,其他功能还是使用多线程执行Redis主干业务使用单线程的原因Redis本质就是一个大的共享资源,共享资源是需要对其进行并发控制的,即使增加了线程,大部分线程也是在等待互斥锁,并行变串行,而且还需要进行…

若依前后端分离版学习笔记(七)—— Mybatis,分页,数据源的配置及使用

一 Mybatis 1、Maven依赖 在ruoyi父项目的pom文件中有一个分页插件的依赖 <!-- pagehelper 分页插件 --> <dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper-spring-boot-starter</artifactId><version&…

灌区信息化智能管理系统解决方案

一、方案背景 灌区作为农业灌溉的重要基础设施&#xff0c;承担着保障粮食安全和促进农业可持续发展的关键作用。然而&#xff0c;传统灌区管理方式普遍存在信息孤岛、数据滞后、调度不精准等问题&#xff0c;导致水资源浪费和管理效率低下。在此背景下&#xff0c;灌区信息化智…

软件包管理、缓存、自定义 YUM 源

1. 软件包管理是啥 你可以把软件包管理器理解成 Linux 的“应用商店 安装工人”&#xff1a; 应用商店&#xff1a;帮你找到软件&#xff08;包&#xff09;安装工人&#xff1a;帮你下载安装、配置、升级、卸载管理账本&#xff1a;记录系统里都安装了啥、版本号是多少、依赖…

Pthon 本质详解

理解 Python 的本质&#xff0c;不能仅仅停留在“它是一门编程语言”这个层面&#xff0c;而要深入其设计哲学、核心机制、以及它在编程世界中所扮演的角色。 可以把 Python 的本质概括为一句话&#xff1a;Python 的本质是一种以“简洁优雅、易于读写”为核心设计哲学&#xf…

在Word文档中用键盘直接移动(复制)内容

如何快速在Word文档中剪切或复制内容到本文档的其他位置&#xff1f;不用剪切或复制&#xff0c;再粘贴&#xff0c;只需要先选中内容&#xff0c;然后按下F2&#xff08;ShiftF2&#xff09;剪切&#xff08;复制&#xff09;内容&#xff0c;再把光标放到目标位置按下回车键就…

VRTE 的应用程序部署到Ubuntu上 报错:bash: ./rb_exmd: No such file or directory

&#x1f6e0;️ 如何在 Ubuntu 上部署 VRTE 3.5 的 AraCM_IPC 应用程序在将 VRTE 3.5 的 AraCM_IPC 应用部署到 Ubuntu 系统时&#xff0c;可能会遇到运行失败的问题&#xff0c;提示类似&#xff1a;bash: ./rb_exmd: No such file or directory这通常并非文件不存在&#xf…

WD5202 非隔离降压转换芯片,220V降5V,输出电流80MA

解锁高效电源新境界&#xff1a;WD5202 非隔离降压转换芯片在当今电子设备飞速发展的时代&#xff0c;高效、稳定且低成本的电源解决方案至关重要。WD5202 作为一款卓越的非隔离降压转换芯片&#xff0c;正以其独特的性能和广泛的适用性&#xff0c;在众多领域崭露头角&#xf…

库函数版独立按键用位运算方式实现(STC8)

位运算&#xff1a;更加简便&#xff0c;单片机的内存就小&#xff0c;占的内存空间小一点案例&#xff1a; #include "GPIO.h" #include "Delay.h" #include "UART.h" // 串口配置 UART_Configuration #include "NVIC.h" // 中断…