题目: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;
}