✏️ 纠错
第 133 题 / 共 155 题
题目描述
对于两个正整数 a,b,他们的最大公因数记为 gcd(a,b)。对于 k>3 个正整数 c1,c2,…,ck,他们的最大公因数为:
gcd(c1,c2,…,ck)=gcd(gcd(c1,c2,…,ck−1),ck)给定 n 个正整数 a1,a2,…,an 以及 q 组询问。对于第 i(1≤i≤q) 组询问,请求出 a1+i,a2+i,…,an+i 的最大公因数,也即 gcd(a1+i,a2+i,…,an+i)。
输入格式
第一行,两个正整数 n,q,分别表示给定正整数的数量,以及询问组数。
第二行,n 个正整数 a1,a2,…,an。
输出格式
输出共 q 行,第 i 行包含一个正整数,表示 a1+i,a2+i,…,an+i 的最大公因数。
输入输出样例
输入 #1
5 3 6 9 12 18 30
输出 #1
1 1 3
输入 #2
3 5 31 47 59
输出 #2
4 1 2 1 4
说明/提示
对于 60% 的测试点,保证 1≤n≤103,1≤q≤10。
对于所有测试点,保证 1≤n≤105,1≤q≤105,1≤ai≤1000。
你真棒!
📝 题目解析
【解析】
1.核心问题:对于每个i,计算gcd(a1+i,a2+i,...,an+i)。
2.关键观察:
设d是所求公因数,则d必能整除任意两数的差:(aj+i) - (ak+i) = ajj-ak。
因此,d是所有aj-ak的公因数,即d整除这些差的最大公因数g。
3.算法步骤:
计算所有ai差值的最大公因数g(通过排序后计算相邻差的gcd)。
对第i组询问,答案为gcd(g,a1+i(因g已包含所有差值信息)。
参考程序
#include <cstdio>
#include <algorithm>
using namespace std;
const int N = 1e5 + 5;
int n, q, a[N], g;
int gcd(int a, int b) {
if (a == 0 || b == 0)
return a + b;
return gcd(b, a % b);
}
int main() {
scanf("%d%d", &n, &q);
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]);
sort(a + 1, a + n + 1);
for (int i = 2; i <= n; i++)
g = gcd(g, a[i] - a[i - 1]);
for (int i = 1; i <= q; i++)
printf("%d\n", gcd(g, a[1] + i));
return 0;
}