博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
codeforce303C-Minimum Modular-剪枝,暴力
阅读量:5157 次
发布时间:2019-06-13

本文共 1450 字,大约阅读时间需要 4 分钟。

题意:就是在一堆数字中,每一个数字对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 
#include
#include
#include
#include
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
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\n",res);}

 

转载于:https://www.cnblogs.com/ckxkexing/p/8447650.html

你可能感兴趣的文章
LeetCode_Recover Binary Search Tree
查看>>
Java中的异常和处理详解
查看>>
redhat更改yum源及安装PHP环境
查看>>
分布式监控系统Zabbix3.2对数据库的连接数预警
查看>>
JavaScript 运行机制:Event事件循环机制
查看>>
<a>标签的href和onclick属性
查看>>
面试题:你的Redis怎么持久化的?
查看>>
Python pyQt4/PyQt5 学习笔记4(事件和信号)
查看>>
經典算法002--快速排序
查看>>
C#发布程序添加其他程序文件
查看>>
manacher算法
查看>>
中间件介绍
查看>>
两个数组相同元素 做聚合
查看>>
JavaScript_1___简单页面倒计时跳转
查看>>
poj3687拓扑排序
查看>>
Android学习第九天----SQLite
查看>>
[转载]回顾MySpace架构的坎坷之路
查看>>
Linux基础学习
查看>>
python基础-----类和实例
查看>>
我的第一个Linux C 程序
查看>>