zoukankan      html  css  js  c++  java
  • 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;
    }
    


  • 相关阅读:
    eclipse导入源码
    servlet文件上传及下载
    MediatorPattern(中介者模式)-----Java/.Net
    IteratorPattern(迭代器模式)-----Java/.Net
    CommandPattern(命令模式)-----Java/.Net
    ResponsibilityChainPattern(责任链模式)-----Java/.Net
    TemplateMethodPattern(模板方法模式)-----Java/.Net
    InterpreterPattern(解释器模式)-----Java/.Net
    ProxyPattern(代理模式)-----Java/.Net
    FlyweightPattern(享元模式)-----Java/.Net
  • 原文地址:https://www.cnblogs.com/javawebsoa/p/3091545.html
Copyright © 2011-2022 走看看