题目:Row GCD
题意:
给定一个数组a1…an,在给定一个数组b1…bm,求出所有GCD(a1+bj,…, an+bj)
思路:参考博客点击
辗转相除不仅适用于两个数 gcd(x, y) = gcd(x, y - x),
它适用于多个数 gcd(a1+bj,a2+bj,…,an+bj)=gcd(a1+bj,a2+bj,…,an+bj−an−1−bj)
最后 gcd(a1+bj,a2+bj,…,an+bj)=gcd(a1+bj,a2−a1,…,an−an−1)
先预处理 gcd(a2−a1,…,an−an−1), 最后O(n)对每个a1+bj 算gcd即可
代码:
#include<bits/stdc++.h>
using namespace std;
#define LL long long
LL gcd(LL a,LL b)
{
return (b>0)?gcd(b,a%b):a;
}
LL a[200100], b[200100];
int main()
{
int n, m;
scanf("%d %d", &n, &m);
LL pre, mcm, b;
for(int i = 1; i <= n; i++)
{
scanf("%lld", &a[i]);
}
if(n == 1)
{
for(int i = 1; i <= m; i++)
{
scanf("%lld", &b);
printf("%lld", a[1] + b);
if(i != m)cout<<" ";
}
cout<<endl;
}
else
{
mcm = a[2] - a[1];
for(int i = 2; i <= n; i++)
{
//cout<<"yes"<<mcm<<" "<<a[i] - a[i-1]<<endl;
mcm = gcd(mcm, abs(a[i]-a[i-1]));
}
for(int i = 1; i <= m; i++)
{
scanf("%lld", &b);
printf("%lld", gcd(a[1] + b, mcm));
if(i != m)cout<<" ";
}
cout<<endl;
}
return 0;
}
本文介绍了一种高效计算给定数组a1...an中,与b1...bm元素组合后的GCD的算法RowGCD。通过辗转相除原理,预处理gcd差分,使得最终查询时间复杂度降低到O(n)。详细步骤包括辗转相除原理的应用和代码实例分析。
291

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



