1. 程式人生 > >C. Powers Of Two 二進位制

C. Powers Of Two 二進位制

題目連結:http://codeforces.com/contest/1095/problem/C
題目大意:給你兩個整數n和k,要求把n拆成k個2的冪的和。1 2 4 8 16…。如果無法做到就輸出NO,能夠做到就輸出YES,並且輸出k個2的冪加數。
在這裡插入圖片描述
思路:開始沒有往二進位制的方向想。只判斷出是能不能滿足條件。方案不知道怎麼構造。
後來用了二進位制。那麼n的二進位制有多少個1.這就是k的最小值。因為可以把高位的1拆成兩個低進位制的1。所以把所有高位的1的全部拆成最低位的1。就是k的最大取值。也就是n個2^0。

思考:因為後面的迴圈結束時沒有判斷所有的低位的和是否<k。所以第二天WA 29。-59。慘痛的教訓。。。

#include<bits/stdc++.h>
using namespace std;
#define LL long long
const int mod=1000000007;

char a[35];
int b[35];

int main()
{
    int n, k, s=0;
    scanf("%d%d",&n,&k);
    if(k>n)
    {
        printf("NO\n");
        return 0;
    }
    for(int i=0;i<32;i++)
    {
        a[i]=((n>>i)&1)+'0';
    }
    for(int i=32;i>=0;i--)
    {
        if(a[i-1]=='1')
        {
            n=i-1;
            for(int j=i-1;j>=0;j--)
            {
                b[j]=a[j]-'0';
                s+=b[j];
            }
            break;
        }
    }
    if(k<s)
    {
        printf("NO\n");
        return 0;
    }
    else
    {
        for(int i=n;i>=0;i--)
        {
            if(k>=s+b[i]&&i>0)
            {
                b[i-1]+=b[i]*2;
                s+=b[i];
                b[i]=0;

            }
            else if(k<s+b[i])
            {
                int m=k-s;
                b[i-1]+=2*m;
                b[i]-=m;
                break;
            }
            else
            {
                printf("NO\n");
                return 0;
            }
        }
        printf("YES\n");
        for(int i=0;i<=n;i++)
        {
            while(b[i]--)
            {
                printf("%d ",(int)pow(2, i));
            }
        }
    }

    return 0;