题目:
题意:
给出一个n和一个k,能否用k个2的x方的数的和等于n。
思路:
将2的前29次方求出,然后从大往小遍历,尽可能的选大的数放入一个map中,记下放入数的次数Size。
如果Size<n||k>n则输出NO。
否则,就将大于1的数进行分解,知道大于等于n为止。
代码如下:
#include <bits/stdc++.h>
using namespace std;
const int maxn=2*1e5+5;
int n,k;
int a[35];
vector<int>v;
map<int,int>ma;
int main()
{
a[0]=1;
for (int i=1;i<31;i++)
a[i]=a[i-1]*2;
scanf("%d%d",&n,&k);
int temp=n,Size=0;
for (int i=30;i>=0&&temp;i--)
{
if (a[i]<=temp)
{
ma[a[i]]=temp/a[i];
Size+=temp/a[i];
temp-=a[i]*(temp/a[i]);
}
}
if(Size>k||n<k)
{
printf("NO\n");
}
else
{
while (Size<k)
{
for (map<int,int>::iterator it=ma.begin();it!=ma.end();it++)
{
if(Size>=k)
break;
//printf("%d %d\n",it->first,it->second);
if(it->first!=1&&it->second)
{
ma[it->first/2]+=2;
Size++;
it->second--;
}
}
}
if(Size>k)
{
printf("NO\n");
}
else
{
printf("YES\n");
for (map<int,int>::iterator it=ma.begin();it!=ma.end();it++)
for (int i=0;i<it->second;i++)
printf("%d ",it->first);
printf("\n");
}
}
return 0;
}