zoukankan      html  css  js  c++  java
  • 2的n次幂

    问题描述

    任何一个正整数都可以用2进制表示,例如:137的2进制表示为10001001。
      将这种2进制表示写成2的次幂的和的形式,令次幂高的排在前面,可得到如下表达式:137=2^7+2^3+2^0
      现在约定幂次用括号来表示,即a^b表示为a(b)
      此时,137可表示为:2(7)+2(3)+2(0)
      进一步:7=2^2+2+2^0 (2^1用2表示)
      3=2+2^0 
      所以最后137可表示为:2(2(2)+2+2(0))+2(2+2(0))+2(0)
      又如:1315=2^10+2^8+2^5+2+1
      所以1315最后可表示为:
      2(2(2+2(0))+2)+2(2(2+2(0)))+2(2(2)+2(0))+2+2(0)
    输入格式
      正整数(1<=n<=20000)
    输出格式
      符合约定的n的0,2表示(在表示中不能有空格)
    样例输入
    137
    样例输出
    2(2(2)+2+2(0))+2(2+2(0))+2(0)
    样例输入
    1315
    样例输出
    2(2(2+2(0))+2)+2(2(2+2(0)))+2(2(2)+2(0))+2+2(0)


    思路

      简单点的话,老老实实算二进制,再输出;这里涉及到每位二进制的指数也要一起分解,即在分解我们的数的途中还要分解,明显的递归。

      但是也可以不用算出二进制,使用位运算直接对二进制进行操作,这里用 137 来演示,具体如下:

      首先我们知道 137 的二进制为:10001001

    1、获取最高位二进制

    1 for(e=0, now=1; now <= n; now<<=1, e++);

    这里的 e 表示当前二进制的位置,也就是我们需要的指数,初始化为 0 位;now 表示 2 的 n 次方,用来与我们输入的数 n 相比较,判断具体要移动多少位。这里我们循环结束后应该是这样子的:

    010001001  原数 137

    100000000  2 的 8 次方 256

    此时, e = 8, now = 256

    2、判断当前位是否是 0 位

    这是大概最精彩的部分

    1 for(;now>0;now>>=1, e--){
    2         if(now & n){
          // 继续
    3   }

    之前我们已经知道了 now 和 n 的二进制,接下来,当循环条件满足时,我们就不断将二进制左移(e--),同时将 now 与 n 按位与,得到如下结果:

    010001001  原数 137

    100000000  2 的 8 次方 256

    000000000  0

    判断条件为假,继续下一次循环:

    010001001  原数 137

    010000000  2 的 7 次方 128,因为我们右移了一位

    010000000  此时不为0

    判断条件为真,继续执行下面的内容,直到把当前的二进制读取完。

    下一次循环结果为

    010001001  原数 137

    001000000  2 的 6 次方 64

    000000000  此时为0

    一直下去......

    3、判断输出

     1 void fun(int n)
     2 {
     3     int now, e;
     4     for(e=0, now=1; now <= n; now<<=1, e++);
     5     cout<<"2";
     6     for(;now>0;now>>=1, e--){
     7         if(now&n){
     8             if(now > 2){      // now 大于2,说明指数大于2,还要继续分解
     9                 cout<<"(";
    10                 fun(e);       // 递归
    11                 cout<<")";
    12             }
    13             if(now == 2);      // 等于2时题目叫我们什么也不做
    14             else if(now == 1){    // 等于1是要输出指数0
    15                 cout<<"(0)";
    16             }
    17             /*
    18             当当前指数分解结束后,要用之前的数减去当前分解的指数,比            
    19             如这里137 = 2^7 + 2^3 + 2^0,在分解完2^7后,继续分解 
    20             2^3 + 2^0
    21             */
    22             n -= now;        
    23             if(n){         // 当然,如果可以继续分解的话,否则这里条件判断是假
    24                 cout<<"+2";
    25             }
    26         }
    27     }
    28 }                          

    完整代码

     1 #include<iostream> 
     2 
     3 using namespace std;
     4 
     5 void fun(int n)
     6 {
     7     int now, e;
     8     for(e=0, now=1; now <= n; now<<=1, e++);
     9     cout<<"2";
    10     for(;now>0;now>>=1, e--){
    11         if(now&n){
    12             if(now > 2){
    13                 cout<<"(";
    14                 fun(e);
    15                 cout<<")";
    16             }
    17             if(now == 2);
    18             else if(now == 1){
    19                 cout<<"(0)";
    20             }
    21             n -= now;
    22             if(n){
    23                 cout<<"+2";
    24             }
    25         }
    26     }
    27 }
    28 int main()
    29 {
    30     int n = 0;
    31     cin>>n;
    32     fun(n);
    33     
    34     return 0;
    35 }
    View Code

  • 相关阅读:
    Codeforces 177G2 Fibonacci Strings KMP 矩阵
    Codeforces Gym100187C Very Spacious Office 贪心 堆
    Codeforces 980F Cactus to Tree 仙人掌 Tarjan 树形dp 单调队列
    AtCoder SoundHound Inc. Programming Contest 2018 E + Graph (soundhound2018_summer_qual_e)
    BZOJ3622 已经没有什么好害怕的了 动态规划 容斥原理 组合数学
    NOIP2016提高组Day1T2 天天爱跑步 树链剖分 LCA 倍增 差分
    Codeforces 555C Case of Chocolate 其他
    NOIP2017提高组Day2T3 列队 洛谷P3960 线段树
    NOIP2017提高组Day2T2 宝藏 洛谷P3959 状压dp
    NOIP2017提高组Day1T3 逛公园 洛谷P3953 Tarjan 强连通缩点 SPFA 动态规划 最短路 拓扑序
  • 原文地址:https://www.cnblogs.com/mabeyTang/p/9880305.html
Copyright © 2011-2022 走看看