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;
}