题意 : 给出一个数 n ,要求你用 k 个二的幂来组成这个数,要求输出这 k 个二的幂的指数,如果有多解情况则优先输出最大指数最小的那一个且要求按字典序输出,不存在则输出 No

分析 : 

先来说一个结论对于一个二的幂例如 2^n 我们可以将其拆成 2^(n-1) + 2^(n-1)

那么对于题目所给出的数 n 我们可以先将其拆成二进制形式,如果当前二进制表示法中 1 的个数已经超过 k 则应该是输出 No

也就是说无论怎么转化都不可能有用更少的二的幂的个数来表示这个数,只能更多,也就是利用上面一拆多的结论

那么接下来就是用上述结论去一位位拆,为了保证拆出来的是符合题目要求的,按如下方式拆

首先为了保证最大的二的幂指数尽量小,我们始终从最高位拆

但是为了不超过 k 这个限制,当 2*最高位的二的幂的数量已经大于当前需要补充的数时候

这时候我们无法使得最大的二的幂被拆掉,所以为了保证字典序最小,我们此时从最低位开始拆

举个例子来说就是假设当前 n = 1010 (这里是二进制表示)、k = 4

那么一开始 n = 2^3 + 2^1 还需要补充 2 个二的幂

那么从最高位开始拆,变成 n = 2^2 + 2^2 + 2^1

此时还差 1 个二的幂,不过这个时候不能去拆最大的二的幂

应该拆 2^1 才能保证字典序

最后 n = 2^2 + 2^2 + 2^0 + 2^0

#include<bits/stdc++.h>
#define LL long long
using namespace std;
;
int k, cnt, lowbit, idx, arr[maxn];
LL n;

int main(void)
{
    lowbit = -;
    scanf("%I64d %d", &n, &k);
    while(n){/// 先把 n 拆成二进制数
        ){
            cnt++;/// n 的二进制表示法中 1 的数量
            arr[idx]++;/// 记录当前二进制 1 所代表到底是哪个幂,例如 arr[2] => 2^2
            )
                lowbit = idx;
        }
        n >>= ;
        idx++;/// n 的二进制表示法中有效位长
    }
    lowbit = (idx-)-lowbit;/// 计算出 n 的二进制表示法中最低位的那个 1 是第几位
    std::reverse(arr, arr+idx);
//----------Debug-------------------
//    for(int i=0; i<idx; i++)
//        printf("%d ", arr[i]);
//    puts("");
//    printf("%d %d\n", idx, lowbit);
//----------Debug-------------------
    if(cnt > k){/// No 的情况
        puts("No");
        ;
    }

     ;; i++){///从最高位开始进行拆分操作
        if(cnt == k) break;
        if(k - cnt < arr[i]) break;
        cnt += arr[i];
        arr[i+] += arr[i]<<;
        arr[i] = ;
        lowbit = max(lowbit, i+);
    }

//------------Wrong!!!-----------------------
//    while(cnt != k){
//        if(arr[lowbit] >= k - cnt){
//            arr[lowbit] -= k-cnt;
//            arr[lowbit+1] += (k-cnt)<<1;
//            cnt = k;
//        }else{
//            arr[lowbit+1] += arr[lowbit]<<1;
//            cnt += arr[lowbit];
//            arr[lowbit] = 0;
//        }
//        lowbit += 1;
//    }
//------------Wrong!!!-----------------------

    while(cnt != k){///Greedy!!!
        cnt++;
        arr[lowbit]--;
        arr[++lowbit] += ;
    }

    puts("Yes");
    ; i<=lowbit; i++){
        while(arr[i]){
            arr[i]--;
            printf(-i);
        }
    }puts("");
    ;
}

Codeforces 916B Jamie and Binary Sequence ( 模拟 && 思维 )的更多相关文章

  1. CodeForces 916B Jamie and Binary Sequence (changed after round) (贪心)

    题意:给定两个数字n,m,让你把数字 n 拆成一个长度为 m 的序列a1,a2,a3...am,并且∑2^ai = n,如果有多组,要求序列中最大的数最小,然后再相同就要求除了最大数字典序最大. 析: ...

  2. Codeforces 916B - Jamie and Binary Sequence (changed after round)

    思路: 先取出二进制的每一位,判断总个数是不是小于等于k,如果大于k则不能构成. 通过观察可以发现,每一位的一个可以转换成下一位的两个,因为要使最大位尽可能小,所以如果最大位的所有的个数都可以转换成下 ...

  3. Jamie and Binary Sequence (changed after round) - CodeForces 916B

    http://codeforces.com/problemset/problem/916/B 好尬啊... #include<cstdio> #include<algorithm&g ...

  4. Jamie and Binary Sequence (changed after round) CodeForces - 916B (贪心)

    链接 大意: 求将n划分为k个2的幂的和, 且最大幂最小,字典序尽量大 比较简单的贪心练习题, 但放在div2的B题感觉偏难了..... 先只考虑最大幂最小, 首先注意到直接按n的二进制划分即可得到最 ...

  5. 【Codeforces Round #457 (Div. 2) B】Jamie and Binary Sequence

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 把n分解成二进制的形式. n=2^a0+2^a1+...+2^a[q-1] 则固定就是长度为q的序列. 要想扩展为长为k的序列. 可 ...

  6. Codeforces Beta Round #13 C. Sequence (DP)

    题目大意 给一个数列,长度不超过 5000,每次可以将其中的一个数加 1 或者减 1,问,最少需要多少次操作,才能使得这个数列单调不降 数列中每个数为 -109-109 中的一个数 做法分析 先这样考 ...

  7. 模拟+思维 HDOJ 5319 Painter

    题目传送门 /* 题意:刷墙,斜45度刷红色或蓝色,相交的成绿色,每次刷的是连续的一段,知道最终结果,问最少刷几次 模拟+思维:模拟能做,网上有更巧妙地做法,只要前一个不是一样的必然要刷一次,保证是最 ...

  8. Codeforces Round #546 (Div. 2) D 贪心 + 思维

    https://codeforces.com/contest/1136/problem/D 贪心 + 思维 题意 你面前有一个队列,加上你有n个人(n<=3e5),有m(m<=个交换法则, ...

  9. SBX(Simulated binary crossover)模拟二进制交叉算子和DE(differential evolution)差分进化算子

    一起来学演化计算-SBX(Simulated binary crossover)模拟二进制交叉算子和DE(differential evolution)差分进化算子 觉得有用的话,欢迎一起讨论相互学习 ...

随机推荐

  1. 获取使用GitHub api和Jira api Authentication的方法

    近段时间在搭建我司的用例管理平台,有如下需求: 1.需要根据项目--版本--轮次的形式来管理项目用例,用例统一保存在git工程. 2.执行用例时,如果用例执行失败,可以通过平台在Jira上提bug. ...

  2. jmap -heap命令用法

    用jmap -heap命令可以查看linux堆内存分布 具体用法 1:先查出tomcat的进程号 例如: 然后执行 jmap -heap 7095 可以打印出整体的堆信息   可以看到经过分配的存活区 ...

  3. 浅谈html5在vr中的应用

    使用过HTML5制作动画过程的开发者都知道,HTML5页面给人一种逼真的感觉,同时HTML也是可以制作VR页面,但是需要你熟练HTML5与JavaScript开发过程,所以在有必要的情况下,我们可以用 ...

  4. 安装libpng库

    一. 安装libpng库前需要先安装zlib库,libpng库依赖zlib库 1.1. zlib库安装 1.1.1. 下载地址:http://www.zlib.net/ 1.1.2. 解压后得到zli ...

  5. thinkphp整合Ueditor编辑器

    编辑器下载地址:http://ueditor.baidu.com/website/download.html#ueditor 放在项目Public或者入口同级目录均可. 前台代码 <div cl ...

  6. django后台集成富文本编辑器Tinymce的使用

    富文本编辑器Tinymce是使用步骤: 1.首先去python的模块包的网站下载一个django-tinymce的包 2.下载上图的安装包,然后解压,进入文件夹,执行: (pychrm直接运行命令pi ...

  7. Java——BufferedImage操作实例

    通过鼠标位置改变图像ColorModel对象索引,从而实现图像像素自动变化 BufferedImage 由图像数据的 ColorModel 和 Raster 组成.Raster 的 SampleMod ...

  8. oracle PL/SQL编程基础知识

    在oracle中使用pl/sql来扩展SQL的功能,使得SQL能够更加的灵活,功能更加强大,效率更高.pl/sql让sql也能执行判断,循环等操作.主要记录一下pl/sql的基本语法和基本条件判断语句 ...

  9. CSS链接使用伪类的顺序

    顺序为:link-visited-hover-active a:link {color: #FF0000} /* 未访问的链接 */ a:visited {color: #00FF00} /* 已访问 ...

  10. 数据库管理利器——Navicat Premium v12.1.25 下载和安装

    目录 1. 按 2. 新功能 3. 安装 4. 激活 5. 下载地址 1. 按 Navicat Premium 是一套数据库管理工具,让你以单一程序同時连接到 MySQL.MariaDB.SQL Se ...