CodeForces Round #183 (303C) - Minimum Modular

    两数a,b同余m,显然(a-b)%m=0.....若有m%p=0...那么(a-b)%p=0....

   将所有的(a[j]-a[i])记录下来...用c[1000000]的表来记...如果一个数p是N对数的同余..那么c[p]=N...

   有了上面的处理,就可以方便的统计出对于当前枚举的md...会产生多少对同余的(将md所有的整数倍c[ ] 加起来)...

   但产生了N对同余的..并不代表要去除N-1个数才行...比如...

   3,6,9,10....(3,6),(3,9),(3,12),(6,9),(6,12),(9,12)...如果当前测试的md=3..那么会有6对同余3的....而实际上最少减去3个数可以保证不出现同余3的情况...

   我做到这里就没想法了...

   看了下别人的代码.. 自己理解了下..很有道理...不过也感觉很大胆...

   其实并不是用md求同余对来计算最少要减去几个数..而是用其剪枝..然后再暴力查找(纯暴力..一个个试..看有多少重复..重复个数是否不大于k)

   剪枝的方式是当前md的同余对>k*(k+1)/2..就找下一个md.... 

   为什么同余对>k*(k+1)/2时就不必要用暴力的方式来判断了?

   考虑一个极端的情况..给的n个数每一个都是md的整数倍..那么显然就有n*(n-1)/2个关于md的同余对...但是只需要去掉n-1个数就可以使得没有同余对了...

   把n-1看成题目要求的k...那么极端情况不就是md的同余对为(k+1)*k/2吗?当md的同余对>(k+1)*k/2,无论如何也要删去k+1个数才能使得没有对于md的同余对出现...

   这个剪枝相当劲爆..虽然每个通过了同余对<=(k+1)*k/2验证的md都要进行一次暴力查找判断...但时间完全ok...


Program:

 

#include<iostream>

#include<stdio.h>

#include<cmath>

#include<string.h>

#include<algorithm>

#include<queue>

#include<stack>

#define ll long long

#define oo 1000000000

using namespace std; 

int a[5005],c[1000005],n;

bool used[1000005];

int main()

{     

       int i,j,k,m; 

       while (~scanf("%d%d",&n,&k))

       {

             for (i=1;i<=n;i++) scanf("%d",&a[i]);

             sort(a+1,a+1+n);

             memset(c,0,sizeof(c));

             for (i=1;i<n;i++)

               for (j=i;j<=n;j++)

                 c[a[j]-a[i]]++; 

             for (i=1;i<=a[n]+1;i++)

             { 

                   m=0;

                   for (j=i;j<=1000000;j+=i) 

                   {

                          m+=c[j];

                          if (m>k*(k+1)/2) goto A;

                   }

                   memset(used,false,sizeof(used));

                   m=0;

                   for (j=1;j<=n;j++)

                   {

                          if (used[a[j]%i]) m++;

                          used[a[j]%i]=true;

                          if (m>k) goto A;

                   }

                   break;

                   A: ;

             }              

             printf("%d\n",i);

       }       

       return 0;

}


 

 

你可能感兴趣的:(codeforces)