zoukankan      html  css  js  c++  java
  • codeforce303C-Minimum Modular-剪枝,暴力

    Minimum Modular

    题意:就是在一堆数字中,每一个数字对m取模不能等于这堆数字中的其他数字,同时给了K个机会可以删除一些数字。求最小的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 <cstdio>
    #include <iostream>
    #include <cstring>
    #include <string>
    #include <algorithm>
    
    using namespace std;
    
    const int maxn = 1000000+5;
    
    int a[maxn],n,k,re[maxn],h[maxn];
    
    int main(){
        scanf("%d%d",&n,&k);
        int max = -1;
        memset(re,0,sizeof(re));
        memset(h,0,sizeof(h));
        for(int i=1;i<=n;i++)
        {    
            scanf("%d",&a[i]);
            if(max < a[i])max = a[i];
        }    
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<i;j++)
            {
                int tmp = a[i] - a[j]>0?a[i]-a[j]:a[j]-a[i];
                h[tmp]++;
            }
        }    
    
        int res, flag =1;
    
        for(int m=1;m<=max+1;m++)
        {
                int tk = k;
                int sum = 0;
                flag = 1;
                for(int i=m;i<=1e6;i+=m)
                {
                    sum+=h[i];                        //剪枝操作
                    if(sum>k*(k+1)/2)break;
                }
                if(sum>k*(k+1)/2)continue;
                res = m;
                for(int i=1; i<=n; i++)
                {
                    if(!re[a[i]%res])re[a[i]%res]++;
                    else 
                    {
                        tk--;                        //这里不能直接把k给减了
                        if(tk<0){flag =0;break;}
                    }
                }
                for(int i=1;i<=n;i++)
                {
                    re[a[i]%m]=0;                    //注意每次都要清零,也可以用memset就是速度慢点
                }
                if(flag)break;
        }
        printf("%d
    ",res);
    }
  • 相关阅读:
    template()方法
    如何引入模板引擎
    为什么使用模板引擎
    计算两个日期之间的天数
    oracle分析函数Rank, Dense_rank, row_number
    Oracle备份与恢复详解
    oracle的操作-表空间
    easyui API
    myeclipse快捷键代码
    Java 解决采集UTF-8网页空格变成问号乱码
  • 原文地址:https://www.cnblogs.com/ckxkexing/p/8447650.html
Copyright © 2011-2022 走看看