给出n,
给出n个数,分别是a1,a2,a3,a4....an;
每次操作可以 选择k个数删掉,前提是2^a1+ 2^a5 + 2^ak (k个数 的2次方之和| 可以不可连续)得到的和,也是2的x次方
问最少删除次数;
思路:直接贪心
我们可以知道 对于 2^k、2^k,是可以看作 2^(k+1)的(因为删除他们的步数都是1)
显然我们得先排个序;
并且把每个元素映射进map
遍历map,从最小的元素开始,
如果 map[i]个数为偶数,那么必然可以全部转化为 2^(i+1)
如果 map[i]个数为奇数,那么必然可以全部转化为 2^(i+1),并且剩下一个map[i],单独剩下的map[i]需要单独的一步去删除
就这样一直转化,最后 要删除的次数就是 map[i]为奇数的个数 了.....
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
#include <queue>
#include <map>
#include <set>
#include <vector>
using namespace std;
const __int64 inf=2147483647;
__int64 tm[1000005];
map<__int64,__int64> sb;
map<__int64,__int64> ::iterator it;
map<__int64,__int64> ::iterator tmp;
int main()
{
__int64 n;
__int64 i,j;
scanf("%I64d",&n);
for (i=1;i<=n;i++)
{
scanf("%I64d",&tm[i]);
}
sort(tm+1,tm+1+n);
for (i=1;i<=n;i++)
{
sb[tm[i]]++;
}
__int64 num=0;
for (it=sb.begin();it!=sb.end();it++)
{
if (it->second%2==0)
{
__int64 tmp=(it->second)/2;
if (!tmp) continue;
__int64 v=it->first;
sb[v+1]+=tmp;
it->second=0;
//sb.erase(it);
}
else
{
num++;
__int64 tmp=(it->second)/2;
if (!tmp) continue;
__int64 v=it->first;
sb[v+1] +=tmp;
it->second=1;
}
}
printf("%I64d\n",num);
return 0;
}