题目链接:点击这里
题目大意:
给出一个长度为
n
n
n 的序列
a
1
,
a
2
,
.
.
.
a
n
a_1,a_2,...a_n
a1,a2,...an ,再给出一个长度为
m
m
m 的序列
b
1
,
b
2
,
.
.
.
b
m
b_1,b_2,...b_m
b1,b2,...bm ,对于第二个序列种的每一个元素
b
j
b_j
bj 求:
g
c
d
(
a
1
+
b
j
,
+
a
2
+
b
j
,
.
.
.
,
a
n
+
b
j
)
gcd(a_1+b_j,+a_2+b_j,...,a_n+b_j)
gcd(a1+bj,+a2+bj,...,an+bj)
题目分析:
更相减损术:
g
c
d
(
a
,
b
)
=
g
c
d
(
a
,
b
−
a
)
gcd(a,b) = gcd(a,b-a)
gcd(a,b)=gcd(a,b−a) ,由此可对所求式进行化简:
g
c
d
(
a
1
+
b
j
,
+
a
2
+
b
j
,
.
.
.
,
a
n
+
b
j
)
gcd(a_1+b_j,+a_2+b_j,...,a_n+b_j)
gcd(a1+bj,+a2+bj,...,an+bj)
=
g
c
d
(
a
1
+
b
j
,
a
2
−
a
1
,
.
.
.
,
a
n
−
a
n
−
1
)
=gcd(a_1+b_j,a_2-a_1,...,a_n-a_{n-1})
=gcd(a1+bj,a2−a1,...,an−an−1)
由此式可以看出我们可以先预处理出
t
m
p
=
g
c
d
(
a
2
−
a
1
,
.
.
.
,
a
n
−
a
n
−
1
)
tmp = gcd(a_2-a_1,...,a_n-a_{n-1})
tmp=gcd(a2−a1,...,an−an−1)
然后对每一个
b
j
b_j
bj ,我们直接求
g
c
d
(
a
1
+
b
j
,
t
m
p
)
gcd(a_1+b_j,tmp)
gcd(a1+bj,tmp) 即可
具体细节见代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<set>
#include<map>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
ll read()
{
ll res = 0,flag = 1;
char ch = getchar();
while(ch<'0' || ch>'9')
{
if(ch == '-') flag = -1;
ch = getchar();
}
while(ch>='0' && ch<='9')
{
res = (res<<3)+(res<<1)+(ch^48);//res*10+ch-'0';
ch = getchar();
}
return res*flag;
}
const int maxn = 2e5+5;
const int mod = 1e9+7;
const double pi = acos(-1);
const double eps = 1e-8;
ll n,m,tmp,a[maxn],b[maxn];
ll gcd(ll a,ll b)
{
return b ? gcd(b,a%b) : a;
}
int main()
{
n = read(),m = read();
for(int i = 1;i <= n;i++)
{
a[i] = read();
if(i != 1) tmp = gcd(tmp,abs(a[i]-a[i-1]));
}
for(int i = 1;i <= m;i++)
{
b[i] = read();
printf("%lld%c",gcd(tmp,a[1]+b[i]),i==n ? '\n' : ' ');
}
return 0;
}