Codeforces 1095C. Powers Of Two——————multiset

C. Powers Of Two

A positive integer x is called a power of two if it can be represented as x = 2 y x=2^y 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 n and k. Your task is to represent n as the sum of exactly k powers of two.

Input

The only line of the input contains two integers n and k (1≤n≤1e9, 1≤k≤2⋅1e5).

Output

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

Otherwise, print YES, and then print k positive integers   b 1 , b 2 , … , b k \ b_1,b_2,…,b_k  b1,b2,,bk such that each of bi is a power of two, and ∑ i = 1 k b i = n ∑_{i=1}^{k}b_i=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


题目就是说,给你n和k,让你用k个   2 n   , 0 ≤ n ≤ 31 \ 2^n\ ,0\le n \le 31  2n ,0n31,使得 ∑ i = 1 k b i = n ∑_{i=1}^{k}b_i=n i=1kbi=n,根据样例可以知道, b i b_i bi可以使重复的。
我们可以知道,对于任何一个正整数,都可以将其写成二进制的加法形式。比如
9 = ( 1001 ) 2 = 2 3 + 2 1 = 8 + 1 = 9 9=(1001)_2 = 2^3+2^1 =8+1=9 9=(1001)2=23+21=8+1=9
此时k = 2,但是我们可以将 2 3 2^3 23分解为 2 2 + 2 2 2^2+2^2 22+22
于是k = 3,此时 9 = 2 2 + 2 2 + 2 0 9=2^2+2^2+2^0 9=22+22+20,在将大的分解
于是k = 4,此时 9 = 2 2 + 2 1 + 2 1 + 2 0 9 = 2^2+2^1+2^1+2^0 9=22+21+21+20,符合题意,输出

   m u l t i s e t    \;multiset\; multiset是一种某个数可以重复出现的集合,它通常以平衡二叉树完成.
在这里插入图片描述

#include<bits/stdc++.h>
// #define SUBMIT
using namespace std;
typedef long long ll;
int main()
{
    #ifdef SUBMIT
        freopen("in.txt","r",stdin);
        freopen("out.txt","w",stdout);
        ll _begin_time = clock();
    #endif

    int n,k;
    multiset<int> s;
    cin>>n>>k;
    int m = n;
    for(int i=0;m;m>>=1,i++)    if(m&1) s.insert(1<<i);
    // for(multiset<int>::iterator it=s.begin();it!=s.end();++it)
    //     cout<<*it<<" ";
    // cout<<endl;
    if(n<k||s.size()>k)  cout<<"NO"<<endl;
    else
    {
        while(s.size()<k)
        {
            int a = *(--s.end()); s.erase(--s.end());
            if(a==1)    break;
            s.insert(a/2);
            s.insert(a/2);
        }
        cout<<"YES"<<endl;
        while(s.size())
        {
            cout<<*s.begin()<<" ";
            s.erase(s.begin());
        }
        cout<<endl;
    }
    #ifdef SUBMIT
        ll _end_time = clock();
        printf("Time: %I64d ms\n",_end_time - _begin_time);
    #endif
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值