CF354C Vasya and Beautiful Arrays(gcd+暴力)

首先gcd最大是原序列最小数,设为m。
如果K>=m-1那么一定都可以变成m的倍数,因此答案就是m
显然答案最小为K+1,因为一定能把所有数都变成K+1的倍数。
于是我们可以在K+1~mn从大到小枚举,数x如果是答案的话,要求每一个数都在[gx,gx+K]之间。我们前缀和统计一下即可。
复杂度 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;
}

猜你喜欢

转载自blog.csdn.net/icefox_zhx/article/details/80782741