题目链接 :
题目大意:
给定a,b数组,求gcd(a1+bj,a2+bj,a3+bj,...,an+bj);
思路:
考虑到每个数都增加k,最大公因数有这样的性质
gcd(a,b)=gcd(|a-b|,a)
gcd满足交换律,可以从序列任何位置开始计算
则原式可转化为
gcd(a1+bj,a2+bj,a3+bj,...,an+bj)=gcd(a1+bj,|a2-a1|,|a3-a2|...|an-an-1|);
可以预处理出G=gcd(|a2-a1|,|a3-a2|...|an-an-1|);
每次计算gcd(a1+bj,G)即可。时间复杂度(nlogn)
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
const int N=2e5+10;
ll a[N],b[N];
ll gcd(ll n,ll m)
{
return m?gcd(m,n%m):n;
}
void solve()
{
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=m;i++) cin>>b[i];
//sort(a+1,a+n+1);
ll tmp=0;
for(int i=2;i<=n;i++){
tmp=gcd(tmp,abs(a[i]-a[i-1]));
}
ll res;
for(int i=1;i<=m;i++){
res=gcd(tmp,a[1]+b[i]);
cout<<res<<' ';
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
int t=1;
while(t--) solve();
}
总结:
别忘了gcd除了辗转相除法还有更相减损术,gcd的交换律蒸的很好用