[GESP202506 五級] 最大公因數

題目描述

對于兩個正整數 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?,,ck?1?),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 10001ai?1000

提交鏈接

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(q?n)

對于題目中說的 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(q?n),顯然會超時。但我們可以利用 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?=ai??a1?,即所有數與第一個數的差。

💡 為什么這個公式成立?

這個公式的核心原理來源于 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(q?n) 優化成了 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" // 中斷…