I. Powers Of Two

     I. Powers Of Two

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

Input

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

Output

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

Otherwise, print YES, and then print kk positive integers b1,b2,…,bk, such that each of bi 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

题目分析:

给出一个数n,问能不能把它拆成k个由2的一次或多次方组成的和。

输出能不能并且输出一种拆法。

分析:

很自然地想到先把n写成2进制,二进制位上每个1的位置对应一个数。

如果二进制上有m个1,答案至少有m个。又因为n可以拆成n个1,所以只要m<=k<=n,就可以拆成k个。

关键是拆,因为每个2的次方数可以拆成2个(每个是它本身除以2),也就是说拆一次,总的数字数目就多一个,只要我们按最大的拆,就可以达到,我们要拆成多少个的结果。假设这个数为8,8可以不拆,个数为1(8)。8拆成2个,每个就是4(4,4),如果要3个,把4拆一下就可以。(4,2,2)。。。。。。最终8可以拆成8个1。也就是8可以拆的范围是1~8。

拆可以用bfs来拆,代码如下:

void depart(int x,int n)
{
    queue<int> q;
    q.push(x);
    while(q.size()!=n)
    {
        int p=q.front();
        q.pop();
        q.push(p/2);
        q.push(p/2);
    }
    while(!q.empty())
    {
        ll num=q.front();
        printf("%lld ",num);
        q.pop();
    }
}

最后,要凑够k个数字,我们还要对其他的进行拆。因为每个数如果不拆的话,它是m,我们先把k-m。剩下的由每个数因为拆增加的个数凑出来。

先选定一个方向,比如从大到小拆。我们可以尽可能地把一个数多的拆。比如最后一个数是u,小于k,我们就可以把u全部拆成1。依次类推,当拆到一定程度,剩下的就输出它自己即可。

关于实现从大到小拆:我们可以先存到 栈stack(由小到大),依次取出大的,放进另一个 队列queue里面,再对队列里的依次拆。

注意要从大到小拆,因为后面大的数可能会超出评测要求。

代码:

#include<stdio.h>
#include<algorithm>
#include<iostream> 
#incl#include<stdio.h>
#include<algorithm>
#include<iostream> 
#include<cmath>
#include<queue>
#include<stack>
#define MIN(x,y) x<y?x:y;
using namespace std;
typedef long long ll;
void depart(int x,int n)
{
    queue<int> q;
    q.push(x);
    while(q.size()!=n)
    {
        int p=q.front();
        q.pop();
        q.push(p/2);
        q.push(p/2);
    }
    while(!q.empty())
    {
        ll num=q.front();
        printf("%lld ",num);
        q.pop();
    }
}
int main()
{
    int n,k;
    scanf("%d%d",&n,&k);
    int u=0;
    int t=n;
    stack<int> qp;
    while(t)
    {
        if(t&1) 
        {
            qp.push(u);
        }
        u++;
        t>>=1;
    }
    if(k>=qp.size()&&k<=n) 
    {
        printf("YES\n");
        if(k==1) 
        {
            ll a=qp.top();
            ll b=pow(2,a);
            printf("%lld\n",b);
        }
        else if(k==qp.size())
        {
            while(!qp.empty())
            {
                ll num=qp.top();
                ll mo=pow(2,num);
                printf("%lld ",mo);
                qp.pop();
            }
        }
        else
        {
            k-=qp.size();
            queue<int> pl;
            int tp=0;
            while(k>0&&!qp.empty())
            {
                int kp=qp.top();
                qp.pop();
                ll p;
                if(kp==0) p=1;
                else p=pow(2,kp);
                k=k-p+1;
                pl.push(kp);
            }
            //能全拆的,拆成1 
            while(pl.size()>1)
            {
                int o=pl.front();
                pl.pop();
                int ko=pow(2,o);
                for(int i=0;i<ko;i++)
                {
                    printf("1 ");
    }
    }
//不能全拆的,按指定个数拆 
int o=pl.front();
ll pp=pow(2,o)+k;
depart(pp-k,pp);
//输出剩下的 
while(!qp.empty())
    {
int num=qp.top();
int mo=pow(2,num);
printf("%d ",mo);
qp.pop();
    }
putchar('\n');
    }
    }
else printf("NO\n");
return 0;
}
​
 

猜你喜欢

转载自www.cnblogs.com/studyshare777/p/12208678.html
今日推荐