CF 1095C Powers Of Two(二进制拆分)
A positive integer xx is called a power of two if it can be represented as x=2y, where y is a non-negative integer. So, the powers of two are 1,2,4,8,16,…
You are given two positive integers nn and k. Your task is to represent nn as the sumof exactly k powers of two.
Input
The only line of the input contains two integers nn and k (1≤n≤109, 1≤k≤2⋅105).
Output
If it is impossible to represent nn as the sum of k powers of two, print NO.
Otherwise, print YES, and then print kk positive integers b1,b2,…,bk such that each of bibi is a power of two, and ∑i=1kbi=n. If there are multiple answers, you may print any of them.
Examples
Input
9 4
Output
YES
1 2 2 4
Input
8 1
Output
YES
8
Input
5 1
Output
NO
Input
3 7
Output
NO
题目意思:给定一个数,让你用1,2,4,8等2的倍数表示出来,并且要用指定的k个数,输出一种即可。
解题思路:我们知道任意一个数都可以通过2的倍数组成,这其中的原因可以通过十进制转换二进制来说明。
如果该数的二进制对应数中1的个数大于k,那么很显然不会有k个2的倍数组成该数;如果恰好相等,那么只需要将二进制各个位上的1转换为对应的十进制即可;如果该数的二进制对应数中1的个数小于k,那么就需要拆分二进制了,这里我从高位来开始拆分,每当高位-1时,对应的下一位将会+2,这里存放二进制的数组里将不再仅仅存放0和1了,这时候存放的是对应二进制位数的个数了,只要拆分到恰够k个即可。同时要注意pow函数的使用,这个函数返回值是double类型的,注意转换。
#include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; int main() { int n,k,counts,i,j,x,y,a,ans; int b[110]; scanf("%d%d",&n,&k); counts=0; x=0; a=n; while(a) { if(a%2) { counts++; } b[x]=a%2; x++; a/=2; } //printf("%d\n",counts); //printf("%d\n",x); if(k<counts||k>n)///不满足条件的情况 { printf("NO\n"); } else { printf("YES\n"); if(counts==k)///直接按照进制,不需要拆分 { for(i=0; i<x; i++) { if(b[i]) { ans=int(pow(2,i)); printf("%d ",ans); } } } else///即k>counts,从高位开始拆分,高位-1,相当于低位+2,counts+1 { y=x-1;///最高位 while(counts!=k)///终止条件 { while(b[y]>=1) { b[y]--; b[y-1]+=2; counts++; if(counts==k) { break; } } y--; } for(i=x-1; i>=0; i--)///输出 { if(b[i]>=1)///注意这里b[i]上的值代表的是该位上对应2^i的个数 { for(j=0; j<b[i]; j++) { ans=int(pow(2,i)); printf("%d ",ans); } } } } } return 0; }