http://codeforces.com/contest/355/problem/Eios
每一个数均可以变成段 [a-k,a], 某一个因子是否被全部的段包含,就是把这个因子以及它的全部倍数当作点,数组
看是否是全部的段包含点spa
假如说全部的 a-k都大于0 那么最小的 k+1这个因子必定是全部段都包含的code
若是有的段被0截断了(a-k不大于0)那么全部段都包含的最大因子就是最小段(0,a)的 ablog
假如全部段都没有被截断,最小可能解是k+1, 而后依次向上枚举 对于全部大于k的因子,每个段要么包含一个点,要么不包含点ci
把全部的段在数组上标记,这样很快就能够断定一个因子是否是被全部的段包含了get
代码:string
#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; }