2018.02.05【GDOI2018】模拟C组——Multiset

Description

Alice 正在玩一个 multiset。最初,集合中只有一个元素 0。每一轮,集合中的每一个元素 x 都有 3 种可能的操作:

1、x 加上 1.即 x = x +1。

2、x 分裂成两个非负整数 y, z。即 x = y + z, 且 y >=0, z >= 0。

3、什么都不做。

注意,在一轮中每个元素只能选择一种操作。

Alice 已经玩了很久了, 但她并不知道自己已经玩了多少轮。 现在给出最终的集合,请你输出 Alice 最少玩的轮数。

Input

第一行为一个整数N,描述最终集合的大小。

第二行为N个非负整数,为最终集合的每一个元素。

Output

输出唯一一行,Alice 最少玩的轮数。

Sample Input

Sample Input 1

1

0

Sample Input 2

4

1 1 1 1

Sample Input 3

5

0 3 0 3 0

Sample Output

Sample Output 1

0

Sample Output 2

3

Sample Output 3

5

Data Constraint

对于 10%的数据,N <= 10,A[i] <= 10

对于 30%的数据,N <= 50,A[i] <= 100

对于 50%的数据,N <= 1000,A[i] <= 10,000

对于 100%的数据,N <= 1,000,000,A[i] <= 1,000,000


思路

经过大佬讲解后,发现这是一道模拟题,不过比较麻烦。


程序

var
  n,s,i,k,ans:longint;
  a:array[0..1000001]of longint;
begin
  readln(n);
  for i:=1 to n do
  begin
    read(k);
    inc(a[k]);
    if ans<k then ans:=k;
  end;
  readln;
  s:=a[0];
  for i:=1 to ans do
    s:=((s+1) shr 1)+a[i];
  while s>1 do
  begin
    s:=(s+1)shr 1;
    inc(ans);
  end;
  writeln(ans);
end.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值