I. Powers Of Two
题目链接
题目大意:给出一个n和k,计算出n由k个2^p(p∈Z+)相加而成,求这k个数的组合。
思路:先算出n的二进制形式,然后计算二进制上有几个1,记为p,并将每个是1的位置对应十进制的数由大到小存入队列中,p是组合成n的最小个数以及队列的size,如果n<k或者k<p,就不存在这种组合,否则就存在。如果存在,意味着p<=k,就需要将队列中的数一一取出除以二,然后再放入队列,此时p++,注意如果取出的是1,就不用除,直接重新放入队列即可,这样子反复操作直到p=k,然后一一pop出队列打印即可。
代码
#include <cstdio>
#include <cstring>
#include <queue>
#include <math.h>
using namespace std;
int d[10005],a[10005];
int change(int n){
int p=0;
while(n){//十进制转化二进制。
d[p++]=n%2;
n/=2;
}
int pp=0;
for(int i=0;i<p;i++){
if(d[i]){
a[pp++]=pow(2,i);//将二进制每一位转化成十进制数。
}
}
return pp;//pp就是n拆出来的最少个数
}
int main(){
queue<int>que;
int n,k;
scanf("%d%d",&n,&k);
int p=change(n);
if(n<k) puts("NO");
else if(k<p) puts("NO");
else{
for(int i=p-1;i>=0;i--){
que.push(a[i]);
}
while(que.size()!=k){
int m=que.front();
if(m>1){
que.pop();
m/=2;
que.push(m);
que.push(m);
}
else{
que.pop();
que.push(1);//是1的话,就弹出再放入,让它到队列最下面。
}
}
puts("YES");
while(!que.empty()){
int res=que.front();
que.pop();
printf("%d ",res);//一个一个pop出来输出
}
}
return 0;
}