• CF 303C——Minimum Modular——————【剪枝】


    Minimum Modular
    time limit per test
    2 seconds
    memory limit per test
    256 megabytes
    input
    standard input
    output
    standard output

    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: .

    Input

    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).

    Output

    Print a single positive integer — the minimum m.

    Sample test(s)
    input
    7 0
    0 2 3 6 7 12 18
    output
    13
    input
    7 1
    0 2 3 6 7 12 18
    output
    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;
    }
    

      

  • 相关阅读:
    Chrome Native Messaging 与本地程序之间的通信
    由于扩展配置问题而无法提供您请求的页面。如果该页面是脚本,请添加处理程序。如果应下载文件,请添加 MIME 映射。
    linux
    maven POM.xml 标签详解 转
    java-线程观察整个生命周期
    java-Web项目开发中Spring整合Junit单元测试
    java-Map集合的四种遍历方式
    Java-8内置的核心函数式接口接口
    正则表达式
    Java-Atomic系列12大类实例讲解和原理分解
  • 原文地址:https://www.cnblogs.com/chengsheng/p/4543843.html
Copyright © 2020-2023  润新知