CodeForces 1459C 数论 GCD
题意
-
首先给出n个数
-
之后给出m个数,每次问之前的n个数加上当前的这个数之后,总体的gcd是多少,也就是答案需要求出m个总体的gcd
思路
-
因为n和m都是2e5的范围,所以必须使用接近线性的算法
-
考虑每次的计算前都是对原数组进行加法运算的改动,所以可以去思考gcd计算中和加减法有关的知识。也就是更相减损术
-
公式:
g c d ( a , b , c ) = g c d ( a , b − a , c − b ) gcd(a, b, c) = gcd(a, b - a, c - b) gcd(a,b,c)=gcd(a,b−a,c−b)
对三个以上的序列也同样成立
- 所以先将第一列数进行从小到大的排序,然后计算出
C = g c d ( a 2 − a 1 , a 3 − a 2 , ⋅ ⋅ ⋅ , a n − a n − 1 ) C = gcd(a_2 - a_1, a_3 - a_2, ···,a_n - a_{n - 1}) C=gcd(a2−a1,a3−a2,⋅⋅⋅,an−an−1)
之后每次取 g c d ( C , a 1 + b j ) gcd(C, a_1 + b_j) gcd(C,a1+bj)就可以了。注意特判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;
}
博客详细介绍了CodeForces 1459C 数论 GCD问题的解决过程。首先,博主解释了题目要求计算n个数在不断加入新的数后的总体GCD。接着,博主提出由于n和m的数量级较大,需要采用近似线性的算法。通过分析gcd的性质,得出gcd(a, b, c) = gcd(a, b - a, c - b)的结论,并对初始数组进行排序。博主给出的解决方案是先计算第一列数的特定gcd,然后在每次询问时,结合新加入的数与之前的结果计算gcd。最后,博主提到了针对特殊情况的处理,例如数组中只有一个元素的情况。"
110371194,10295944,Python播放音频指南,"['Python', '音频处理', '播放音频', '多媒体开发', 'pydub']
336

被折叠的 条评论
为什么被折叠?



