CodeForces - 305C Ivan and Powers of Two(数学+思维)

CodeForces - 305C Ivan and Powers of Two(数学+思维)

Ivan has got an array of n non-negative integers a1, a2, …, an. Ivan knows that the array is sorted in the non-decreasing order.

Ivan wrote out integers 2a1, 2a2, …, 2an on a piece of paper. Now he wonders, what minimum number of integers of form 2b (b ≥ 0) need to be added to the piece of paper so that the sum of all integers written on the paper equalled 2v - 1 for some integer v (v ≥ 0).

Help Ivan, find the required quantity of numbers.

Input
The first line contains integer n (1 ≤ n ≤ 105). The second input line contains n space-separated integers a1, a2, …, an (0 ≤ ai ≤ 2·109). It is guaranteed that a1 ≤ a2 ≤ … ≤ an.

Output
Print a single integer — the answer to the problem.

Examples
Input
4
0 1 1 1
Output
0
Input
1
3
Output
3
Note
In the first sample you do not need to add anything, the sum of numbers already equals 23 - 1 = 7.

In the second sample you need to add numbers 20, 21, 22.

题目大意:
给你一组非递减数列 a1,a2,a3,…an, 让你求 2a1 + 2a2 +…2an 再加多少个2ki 使得 2a1 + 2a2 +…2an+ 2k1 + 2k2 +…2km =2v -1 ,问最少的 k的个数。
解题思路:
2a1 + 2a2 +…2an+ 2k1 + 2k2 +…2km =2v -1 我们首先把1=20 移到等式的左边,等式变成20+ 2a1 + 2a2 +…2an+ 2k1 + 2k2 +…2km =2v .
我们考虑 两个相同的 a 相加就能变成 a+1。 比如a1=2,a2=2, 那么22 +22 =8 = 23 所以要变成2v 就需要有两个 2v-1 相加。
如果 两个相邻的数不相等怎样才能变成2的指数呢? 比如 a1=2 a2=4.
要想让 24 变成25 就需要 加上一个24 ,那24 哪来的呢?就需要两个 23 ,23 就是两个22 相加 我们这里有一个22 了 所以要加的k1=2 ,然后就有23 了 再加的第二个数k2=3,这时候就出现 24 了,再加上本来有的 24 就出现 25 了 所以需要加的个数是 a2-a1
代码实现细节:
(1)我们用一个优先队列存一下所有的a,按从小到大排,别忘了往队列里加上个0,因为1 移到左边就是20

priority_queue<ll,vector<ll>,greater<ll> > q;

(2)每次弹出两个数t1,t2来,判断一下,如果t1==t2就让 t1+1入队(因为两个2t1相加是 2t1+1),如果不相等就让ans+=(t2-t1),前面解释了为什么了。然后把t2+1入队。

	while(!q.empty())
	{
	
		ll t1=q.top();
		q.pop();
		ll t2=q.top();
		q.pop();
		if(t1==t2)
		{
			if(q.empty())
				break;
			else
				q.push(t1+1);
		}
		else
		{
			ans+=(t2-t1);
			if(q.empty())
				break;
			else
				q.push(t2+1);
		}
	}

(3)最后是z终止条件,只要弹出两个数来后,队列里没数了,就说明已经全部安排上了,就可以终止了。


感觉这个题思维还是很巧妙的,值得收藏一波。

  • AC代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#define ll long long
using namespace std;
int n;
priority_queue<ll,vector<ll>,greater<ll> > q;
int main()
{
	cin>>n;
	ll ans=0;
	while(n--)
	{
		ll t;
		scanf("%lld",&t);
		q.push(t);
	}
	q.push(0);
	while(!q.empty())
	{
	
		ll t1=q.top();
		q.pop();
		ll t2=q.top();
		q.pop();
		if(t1==t2)
		{
			if(q.empty())
				break;
			else
				q.push(t1+1);
		}
		else
		{
			ans+=(t2-t1);
			if(q.empty())
				break;
			else
				q.push(t2+1);
		}
	}
	cout<<ans<<endl;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43179892/article/details/84576945