标签:mes std amp cli through 序列 return names int
【问题描述】
给定一个可重集合,一开始只有一个元素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
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 }
标签:mes std amp cli through 序列 return names int
原文地址:https://www.cnblogs.com/tpgzy/p/8974908.html