1. 程式人生 > >【CodeForces - 305C】Ivan and Powers of Two(思維)

【CodeForces - 305C】Ivan and Powers of Two(思維)

C. Ivan and Powers of Two

time limit per test

0.5 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

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 2^{a1}, 2^{a2}, ..., 2^{an} on a piece of paper. Now he wonders, what minimum number of integers of form 2^b (b ≥ 0) need to be added to the piece of paper so that the sum of all integers written on the paper equalled 2^v - 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

Copy

4
0 1 1 1

output

Copy

0

input

Copy

1
3

output

Copy

3

Note

In the first sample you do not need to add anything, the sum of numbers already equals 2^3 - 1 = 7.

In the second sample you need to add numbers 2^0,2^1,2^2.

思路:

一開始沒想到怎麼做,但是看資料量這麼大就一定是思維題,寫了寫發現要求得就是許多個2^k的加和,並且和還是2的指數,而由2的指數得到2的指數,那就是兩個相同的相加使得指數加1。即2^{k}+2^{k}=2*2^k=2^{k+1},因此我們只要暴力遍歷所有的數,找相鄰兩個數之間的差值就是我們要補的數的多少,如果一對數是1,3那麼我們新增幾個數後應該變為4(使得兩個數變為1個)。小的數在不斷新增數的過程中會增加,直到和大的數相等,這時我們不必在加新的數,只需要這兩個數相加就好。由此我們能發現要補的數是t1、t1+1....t2-1(t1\leq t2)。因此這兩個數之間需要補的數是t2-t1個。

這裡我用來優先佇列,但是直接用陣列模擬應該也是可以的。greater從小到大的優先順序佇列。

ac程式碼:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<stack>
#include<map>
#include<string.h>
#define ll long long
using namespace std;
priority_queue<ll,vector<ll>,greater<ll> > que;
ll a[110100];
int main() 
{
	int n;
	scanf("%d",&n);
	a[0]=0;
	que.push(0);
	for(int i=1;i<=n;i++)
	{
		scanf("%lld",&a[i]);
		que.push(a[i]);
	}
	ll ans=0;
	while(!que.empty())
	{
		ll t1=que.top();
		que.pop();
		ll t2=que.top();
		que.pop();
		if(t1==t2)
		{
			if(que.empty())
			{
				break;
			}
			else
			{
				que.push(t1+1);
			}
		}
		else
		{
			int dis=t2-t1;
			ans+=dis;
			if(que.empty())
			{
				break;
			}
			else
			{
				que.push(t2+1);
			}
		}
	}
	cout<<ans<<endl;
	return 0;
}

 

 cf上大佬們寫的程式碼就行簡單,自己寫的還是太麻煩了,ORZ。

個人的理解:
感覺就是,0~v時,我一開時什麼都沒有,然後從0~v需要0~v-1這幾個數和0這個數。而0我一開始有1個
那麼0~v-1一共有v個那麼我一開始缺少k個。然後讀入數後進行合併並放入set中,那麼set中是我現在有的,即我不用再額外找這些數了。
但是set中的最大值就是v,而這個本來就不需要,因此不應該算在已有的裡面,所以現在已有的是s.size()-1。
需要的-已經有的=要補的 

#include<bits/stdc++.h>
using namespace std;
set<int> s;
int a,n,k;
int main(){
	cin>>n;
	while (n--){
		cin>>a;
		while (s.count(a))
		s.erase(a),a++;
		s.insert(a),
		k=max(k,a);//能到的最大值,應該就是v    讀入的數的最大值再加一 
	}
	cout<<k-s.size()+1;
}