Codeforces Round #529 -C- Powers Of Two(二进制拆分)

A positive integer xx is called a power of two if it can be represented as x=2yx=2y, where yy is a non-negative integer. So, the powers of two are 1,2,4,8,16,…1,2,4,8,16,….

You are given two positive integers nn and kk. Your task is to represent nn as the sumof exactly kk powers of two.

Input

The only line of the input contains two integers nn and kk (1≤n≤1091≤n≤109, 1≤k≤2⋅1051≤k≤2⋅105).

Output

If it is impossible to represent nn as the sum of kk powers of two, print NO.

Otherwise, print YES, and then print kk positive integers b1,b2,…,bkb1,b2,…,bk such that each of bibi is a power of two, and ∑i=1kbi=n∑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的数量为最小需要的二进制数,最多需要多少,是n个,因为都可以用1来表示,然后大一位的数代替即可,故可以表示的范围为2进制1的个数到n,这是可以表示出来的,可以从1进行累加到满足,也可以从高位拆分,高位拆分在一般情况下可能更快

下面是代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>

using namespace std;

long long int a[505];
int m=0;
int tochange(int x) {

	while(x) {
		a[m++]=x%2;
		x/=2;
	}
}//转成2进制 
int main() {

	int n,k;
	scanf("%d%d",&n,&k);
	int ans=0;
	tochange(n);
	for(int t=m-1; t>=0; t--) {
		if(a[t]==1) {
			ans++;
		}
	}
	if(k<ans||k>n) {
		cout<<"NO"<<endl;
	}//不满足的情况 
	else {
		cout<<"YES"<<endl;
		if(ans==k) {//如果直接等于就不用拆分了 
			for(int t=0; t<m; t++) {
				if(a[t]==1) {
					long long int s1=pow(2,t);
					printf("%lld ",s1);
				}
			}
		} else {//从高位拆分,高位-1,低位+2,ans+1 
			int p=m-1;
			while(ans!=k) {
				while(a[p]>=1) {
					a[p]--;
					a[p-1]+=2;
					ans++;
					if(ans==k)
					{
						break;
					}
				}
				p--;
			}//输出 
			for(int t=m-1; t>=0; t--) {
				if(a[t]>=1) {
					for(int j=0; j<a[t]; j++) {
						long long int s2=pow(2,t);
						printf("%lld ",s2);
					}
				}
			}
		}
	}
	return 0;
}

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

black-hole6

你的鼓励将是我创作的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值