• NOI-OJ 2.2 ID:8758 2的幂次方表示


    思路

    • 可以把任意一个数转化为2a+2b+2c+...+2n
      • 例如137的二进制为10001001,这就等效于27+23+2^0
      • 以上结果如何通过程序循环处理呢?需要把数字n分解为上述公式,对指数(a,b,...n)依次进行递归
      • 要对整个结果进行递归生成字符串组后一次性输出比较麻烦,但若是递归输出就会很简单。

    算法流程

    1. 将数字n的幂次方组合信息计算出来,存放在数组中
    2. 输出每一个加数项的底数和空格,指数通过递归方式输出
    cout<<"2(";
    mici(p);
    cout<<")";
    

    第1步的处理方法有多种,可以使用数组,也可以使用按位运算,详见例程

    例程1

    #include<iostream>
    using namespace std;
    void power(int n){
    	int i;
    	int plusFlag=1;
    	for(i=15; i>=0; i--){
    		if(n&(1<<i)){								//按位运算
    			if(plusFlag==1)		plusFlag=0;         //只有一次不输出“+”
    			else				printf("+");
    			if(i==0)			printf("2(0)");	    //临界点 
    			else if(i==1)		printf("2");		//临界点 
    			else if(i==2)		printf("2(2)");	    //临界点 
    			else{
    				printf("2(");
    				power(i);                           //递归
    				printf(")");
    			}
    		}
    	}
    }
    int main(){
    	int n;
    	cin>>n;
    	power(n);
    	return 0; 
    }
    

    该程序使用了按位运算和移位运算:

    移位运算

    左移位运算“a<<b”,可以将a的二进制位左移b位,右边补0,左边移出的丢弃
    右移位运算“a>>b”,可以将a的二进制位右移b位,左边补0,右边移动的丢弃
    

    例1:137在4字节表示的情况下为00000000 00000000 00000000 10001001

    00000000 00000000 00000000 10001001 >>4 得到:

    00000000 00000000 00000000 00001000

    00000000 00000000 00000000 10001001 <<4 得到:

    00000000 00000000 00001000 10010000

    同时可以看到,左移1位在左边没有有效位(1)溢出的情况下,相当于乘2,右移1位相当于除2(只保留整数部分)

    按位运算

    1. 0&0-->0		0&1-->0		1&0-->0		1&1-->1
    2. 0|0-->0		0|1-->1		1|0-->1		1|1-->1
    3. ^0-->1 		^1-->0
    

    运算规则见例子:

    10101010 & 01010101 ---> 00000000	//170 & 85 ---> 0
    10101010 | 01010101 ---> 11111111	//170 | 85 ---> 127
    ^10101010			---> 01010101	//^170	   ---> 85
    ^11111111			---> 00000000	//^127     ---> 0
    

    通过按位、移位运算我们可以对数字的比特位进行操作,但功能不仅限于此,在很多题目中,善用按位和移位运算可以帮助我们轻松解决问题,要善于灵活应用,本题就是一个例子。按位和移位运算都是CPU的基本指令,所以这些运算的效率是比较高的。

    自反赋值运算符

    和其它运算符一样,按位和移位也有自反赋值运算符,方便使用:

    a<<=b	//a=a<<b;
    a>>=b	//a=a>>b;
    a&=b	//a=a&b;
    a|=b	//a=a|b;
    

    例程2

    #include<iostream>
    using namespace std;
    void power(int n){
    	int jishu[16]={0};		    //存放级数信息(每个幂次的指数) 
    	int count=0;			    //有几个加法项 (幂次) 
    	int i=0;			        //i用于计算指数 
    	while(n){
    		if(n%2)	jishu[count++]=i;
    		n/=2;
    		i++;			        //每做一次除法,指数增加1 
    	}
    	//这里的思路是:共出现了count次1,第i个1出现的位置是jishu[i],
    	//所以jishu[i]代表的是第i个1的级数,即2^jishu[i] 
    	for(int i=count-1; i>=0; i--){
    		if(jishu[i]==0)		    printf("2(0)");		//临界值 
    		else if(jishu[i]==1)	printf("2");		//临界值 
    		else if(jishu[i]==2)	printf("2(2)");		//临界值 
    		else{
    			printf("2(");
    			power(jishu[i]);
    			printf(")");
    		}
    		if(i!=0)	printf("+");                    //最后一次不输出“+”
    	}
    }
    int main(){
        int n;
        cin>>n;
    	power(n);
        return 0;
    }
  • 相关阅读:
    mysql CREATE USER
    ConvertHelper 通用类
    自定义属性
    为什么建议使用你LocalDateTime,而不是Date?
    使用IDEA插件Alibaba Cloud Toolkit工具一键部署本地应用到ECS服务器
    IDEA-SpringBoot项目设置热部署
    CentOS7中MySQL跨机器数据迁移
    Centos7 使用YUM安装Mariadb
    Linux下svn服务器迁移
    java dateutil工具类Date.add()
  • 原文地址:https://www.cnblogs.com/lfyzoi/p/6703495.html
Copyright © 2020-2023  润新知