CodeForces 1459C 数论 GCD
CodeForces 1459C 数论 GCD
题意
-
首先给出n个数
-
之后给出m个数,每次问之前的n个数加上当前的这个数之后,总体的gcd是多少,也就是答案需要求出m个总体的gcd
思路
-
因为n和m都是2e5的范围,所以必须使用接近线性的算法
-
考虑每次的计算前都是对原数组进行加法运算的改动,所以可以去思考gcd计算中和加减法有关的知识。也就是更相减损术
-
公式:
\[gcd(a, b, c) = gcd(a, b - a, c - b)
\]
对三个以上的序列也同样成立
- 所以先将第一列数进行从小到大的排序,然后计算出
\[C = gcd(a_2 - a_1, a_3 - a_2, ···,a_n - a_{n - 1})
\]
之后每次取 \(gcd(C, a_1 + b_j)\)就可以了。注意特判a数组中只有一个的情形。
AC代码
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
long long gcdd(long long a, long long b)
{
if (!b)
{
return a;
}
else
{
return gcdd(b, a % b);
}
}
int n, m;
long long aa[200005];
long long bb[200005];
int main()
{
cin >> n >> m;
long long gd;
for (int i = 1; i <= n; ++i)
{
scanf("%lld", &aa[i]);
}
sort(aa + 1, aa + n + 1);
int co = 0;
bb[0] = 0;
bb[++co] = aa[1];
for (int i = 2; i <= n; ++i)//去重
{
if (aa[i] != aa[i - 1])
{
bb[++co] = aa[i];
}
}
gd = bb[co] - bb[co - 1];
for (int i = co - 1; i >= 2; --i)
{
gd = gcdd(gd, bb[i] - bb[i - 1]);
}
for (int i = 1; i <= m; ++i)
{
long long xx;
scanf("%lld", &xx);
printf("%lld ", co == 1 ? xx + bb[1] : gcdd(gd, bb[1] + xx));
}
return 0;
}