首先gcd最大是原序列最小数,设为m。
如果K>=m-1那么一定都可以变成m的倍数,因此答案就是m
显然答案最小为K+1,因为一定能把所有数都变成K+1的倍数。
于是我们可以在K+1~mn从大到小枚举,数x如果是答案的话,要求每一个数都在[gx,gx+K]之间。我们前缀和统计一下即可。
复杂度
O(wlogw)
O
(
w
l
o
g
w
)
#include <bits/stdc++.h>
using namespace std;
#define uint unsigned int
#define inf 0x3f3f3f3f
#define N 300010
inline char gc(){
static char buf[1<<16],*S,*T;
if(S==T){T=(S=buf)+fread(buf,1,1<<16,stdin);if(T==S) return EOF;}
return *S++;
}
inline int read(){
int x=0,f=1;char ch=gc();
while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=gc();}
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=gc();
return x*f;
}
int n,K,a[N],c[1000010];
int main(){
// freopen("a.in","r",stdin);
n=read();K=read();int mn=inf,mx=0;
for(int i=1;i<=n;++i) a[i]=read(),c[a[i]]++,mn=min(mn,a[i]),mx=max(mx,a[i]);
for(int i=1;i<=mx;++i) c[i]+=c[i-1];
if(K>=mn-1){printf("%d\n",mn);return 0;}
for(int i=mn;i>K;--i){
int res=c[K];
for(int j=i;j<=mx;j+=i)
res+=c[min(j+K,mx)]-c[j-1];
if(res==n){printf("%d\n",i);return 0;}
}return 0;
}