N个不同的数a[1],a[2]...a[n],你可以从中去掉K个数,并且找到一个正整数M,使得剩下的N - K个数,Mod M的结果各不相同,求M的最小值。
Input
第1行:2个数N, K,中间用空格分隔,N表示元素的数量,K为可以移除的数的数量(1 <= N <= 5000, 0 <= K <= 4, 1 <= a[i] <= 1000000)。
Output
输出符合条件的最小的M。
Input示例
5 1
1
2
10
11
12
Output示例
4
——————————————————————————————————————————
跟着tjm大爷写了一波
首先 根据抽屉原理显然m>=(n-K)
那么我们可以枚举(n-k)到mx的所有情况
当然这样肯定会T
怎样去计算几个数同余的情况呢
如果v[i]≡v[j](mod m),则有m|(v[i]-v[j]),
因此我们可以n^2预处理一波
每次枚举到一个m我们可以计算他所有的倍数在 n 个数差中出现的情况(cnt)
如果cnt>=(k+1)*k/2 那么至少有k+1个数同余(这是最坏情况下)
加了这样一波剪枝之后就完全可以AC辣
一开始数组开小T了(我居然不知道o2下数组开小了会T QAQ) 改了一波之后还是蛮快的2333
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int M=1e5+7,N=1000007; int read(){ int ans=0,f=1,c=getchar(); while(c<'0'||c>'9'){if(c=='-') f=-1; c=getchar();} while(c>='0'&&c<='9'){ans=ans*10+(c-'0'); c=getchar();} return ans*f; } int n,k,mx,v[M],vis[N],f[N]; int main() { n=read(); k=read(); if(n+1<=k) return puts("1"),0; for(int i=1;i<=n;i++) v[i]=read(),mx=max(mx,v[i]); sort(v+1,v+1+n); for(int i=1;i<=n;i++) for(int j=i+1;j<=n;j++) f[v[j]-v[i]]++; for(int i=n-k;i<=mx;i++){ int cnt=0; for(int j=1;i*j<=mx;j++) cnt+=f[i*j]; if(cnt>(k*(k+1)>>1)) continue; cnt=0; for(int j=1;j<=n;j++){ int now=v[j]%i; if(vis[now]!=i) vis[now]=i; else cnt++; } if(cnt<=k) return printf("%d ",i),0; } return 0; }