You have been given n distinct integers a1, a2, ..., an. You can remove at most k of them. Find the minimum modular m (m > 0), so that for every pair of the remaining integers(ai, aj), the following unequality holds: .
The first line contains two integers n and k (1 ≤ n ≤ 5000, 0 ≤ k ≤ 4), which we have mentioned above.
The second line contains n distinct integers a1, a2, ..., an (0 ≤ ai ≤ 106).
Print a single positive integer — the minimum m.
7 0
0 2 3 6 7 12 18
13
7 1
0 2 3 6 7 12 18
7
参考:http://www.cnblogs.com/Lyush/archive/2013/05/14/3077258.html
题目大意:给你n个数,你可以从中删除最多k个数,使得剩余的所有数对m取余没有同余的,求最小的m。
解题思路:首先想到暴力,从小到大枚举m,然后判断n个数中对m取模同余个数有多少,如果超出k就枚举更大的m。然而这样的话,时间复杂度为O(n*1e6)。然后在网上找了博客看,但是有些地方当时自己感觉很不好理解的,这里做下自己的解释。1.首先这里用了一个剪枝,这个剪枝能节省大量时间。因为如果有k+1个数都是对m取模同余,那么只需删除k个数,就可以让剩下的数(只剩下一个数)不同余,那么从k+1个同余的数中取出2个数组成同余对的组合数就有C(2,k+1)种,即k*k+1/2种,那么如果对m取模同余的同余对的组合数大于k*k+1/2种,说明无法删除k个数使得剩下的数不同余。2.然后暴力判断此时满足1步骤的m作为模是否能满足同余的数小于k个。
#include<bits/stdc++.h> using namespace std; #define max(a,b) (a)>(b)?(a):(b) const int maxn=1e6+100; int num[maxn]; int a[5500]; bool flag[maxn]; int dif(int a,int b){ return a>b? a-b:b-a; } int main(){ int n,k,i,j,maxa,m,mark,sum,cn,mod; maxa=-1; while(scanf("%d%d",&n,&k)!=EOF){ memset(num,0,sizeof(num)); for(i=0;i<n;i++){ scanf("%d",&a[i]); maxa=max(a[i],maxa); } //首先应知道a%m==b%m --> |a-b|%m==0 for(i=1;i<n;i++){ for(j=0;j<i;j++){ //不同类型的同余对各有多少 num[dif(a[i],a[j])]++; } } for(m=1;m<=maxa;m++){ sum=0; for(i=m;i<=maxa;i+=m){ //这里i+=m的原因是,这样能保证同余对 对于对之间也都是同余的,即这样挑出的组合中所有数都是同余的。 sum+=num[i]; // if(sum>k*(k+1)/2){ //剪枝 break; } } if(sum>k*(k+1)/2){ continue; } cn=0,mark=0; for(j=0;j<n&&(!mark);j++){ //暴力判断m是否满足题目的要求 mod=a[j]%m; if(!flag[mod]){ flag[mod]=1; }else{ cn++; if(cn>k){ mark=1; } } } for(j=0;j<n;j++){ //还原 flag[a[j]%m]=0; } if(!mark){ mark=m; break; } } printf("%d ",mark); } return 0; }