http://codeforces.com/contest/355/problem/E
每个数都可以变成段 [a-k,a], 某一个因子是否被所有的段包含,就是把这个因子以及它的所有倍数看成点,
看是不是所有的段包含点
假如说所有的 a-k都大于0 那么最小的 k+1这个因子一定是所有段都包含的
如果有的段被0截断了(a-k不大于0)那么所有段都包含的最大因子就是最小段(0,a)的 a
假如所有段都没有被截断,最小可能解是k+1, 然后依次向上枚举 对于所有大于k的因子,每一个段要么包含一个点,要么不包含点
把所有的段在数组上标记,这样很快就可以判定一个因子是不是被所有的段包含了
代码:
#include<iostream> #include<stack> #include<cstdio> #include<queue> #include<cstring> #include<algorithm> #include<vector> #include<set> #include<map> #include<string> #include<cmath> using namespace std; typedef long long ll; typedef pair<int,int> pp; const double eps=1e-6; const int INF=0x3f3f3f3f; const int N=1000005; int d[N]; int main() { //freopen("data.in","r",stdin); int n,k; while(cin>>n>>k) { memset(d,0,sizeof(d)); int m=INF; for(int i=0;i<n;++i) { int l,r; cin>>r; m=min(m,r); if(m<=k+1) continue; l=r-k; ++d[l];--d[r+1]; } if(m<=k+1) cout<<m<<endl; else { for(int i=1;i<=1000000;++i) d[i]+=d[i-1]; int ans=k+1; for(int i=k+2;i<=1000000;++i) { int num=0; for(int j=i;j<=1000000;j+=i) num+=d[j]; if(num==n) ans=i; } cout<<ans<<endl; } } return 0; }