清北day2 题目:集合
Posted tpgzy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了清北day2 题目:集合相关的知识,希望对你有一定的参考价值。
【问题描述】
给定一个可重集合,一开始只有一个元素0 。然后你可以操作若干轮,每一
轮,你需要对于集合中的每个元素 x 进行如下三种操作之一:
1、将 x 变为 x +1。
2 、将 x 分裂为两个非负整数 y,z,且满足 x = y + z 。
3、什么都不做。
每一轮,集合中的每个元素都必须进行上面三个操作之一。
对于一个最终的集合,你的任务是判断至少进行了多少轮。
【输入文件】
第一行为一个正整数n ,表示集合的最终大小。
第二行为n 个非负整数,描述集合中的元素。
【输出文件】
输出一个非负整数,为最少的轮数。
【输入输出样例】
multiset.in multiset.out
5
0 0 0 3 3
5
【数据规模和约定】
设集合中最大的元素为m 。
对于10% 的数据,满足n ≤10,m ≤10。
对于30%的数据,满足n ≤ 50,m ≤100。
对于50%的数据,满足n ≤1000 ,m ≤10000。
对于100% 的数据,满足1≤ n ≤1000000,0 ≤ m ≤100000
思路:挺不错的个水题,为什么这样说呢,其实就是如果一个数不是0,那就让他减一,若是0,就将俩个0合并起来,比如说这个样例:0 0 0 3 3 先将3-1,再把俩个0合并,就变成了0 0 2 2 2 ,然后再进行这样的操作,0 1 1,在进行一遍成了0 0 0,继续0 0,最后成了0,这一共进行了5轮。但是我们模拟的话,100%的数据肯定是过不了的,所以我们要想方法,怎样做呢,看代码:
1 #include <cstdio> 2 #include <iostream> 3 #include <algorithm> 4 #include <cstring> 5 #include <climits> 6 #include <cstdlib> 7 #include <cmath> 8 #include <queue> 9 #include <vector> 10 #include <utility> 11 using namespace std; 12 const int MAXN = 5e6 + 60, MX = 1e6; 13 int N, a[MAXN], cnt[MAXN], res, lim;//res统计答案||lim统计里面的最大值 14 //cnt桶排 15 int main() 16 { 17 freopen("multiset.in", "r", stdin); 18 freopen("multiset.out", "w", stdout); 19 scanf("%d", &N);//输入最后的序列长度 20 for (int i = 1; i <= N; ++i) { 21 scanf("%d", &a[i]);//输入最后序列的变化 22 lim = max(lim, a[i]);//最大的值 23 ++cnt[a[i]];//桶排 24 } 25 int l = 0, z = cnt[0];//z记录有多少个0 26 for (int i = 1; i <= lim; ++i) { 27 ++res; 28 z = (z + 1) / 2; 29 z += cnt[i]; 30 } //z 统计个数,进行折半 31 for (; z > 1; z = (z + 1) / 2) ++res;//若还有剩余则直接向上取整折半就好 32 printf("%d\n", res); 33 return 0; 34 }
以上是关于清北day2 题目:集合的主要内容,如果未能解决你的问题,请参考以下文章