洛谷P1010 [NOIP1998 普及组] 幂次方 C语言/C++

[NOIP1998 普及组] 幂次方

题目描述

任何一个正整数都可以用 2 2 2 的幂次方表示。例如 $137=27+23+2^0 $。

同时约定方次用括号来表示,即 a b a^b ab 可表示为 a ( b ) a(b) a(b)

由此可知, 137 137 137 可表示为 2 ( 7 ) + 2 ( 3 ) + 2 ( 0 ) 2(7)+2(3)+2(0) 2(7)+2(3)+2(0)

进一步:

7 = 2 2 + 2 + 2 0 7= 2^2+2+2^0 7=22+2+20 ( 2 1 2^1 21 2 2 2 表示),并且 3 = 2 + 2 0 3=2+2^0 3=2+20

所以最后 137 137 137 可表示为 2 ( 2 ( 2 ) + 2 + 2 ( 0 ) ) + 2 ( 2 + 2 ( 0 ) ) + 2 ( 0 ) 2(2(2)+2+2(0))+2(2+2(0))+2(0) 2(2(2)+2+2(0))+2(2+2(0))+2(0)

又如 1315 = 2 10 + 2 8 + 2 5 + 2 + 1 1315=2^{10} +2^8 +2^5 +2+1 1315=210+28+25+2+1

所以 1315 1315 1315 最后可表示为 2 ( 2 ( 2 + 2 ( 0 ) ) + 2 ) + 2 ( 2 ( 2 + 2 ( 0 ) ) ) + 2 ( 2 ( 2 ) + 2 ( 0 ) ) + 2 + 2 ( 0 ) 2(2(2+2(0))+2)+2(2(2+2(0)))+2(2(2)+2(0))+2+2(0) 2(2(2+2(0))+2)+2(2(2+2(0)))+2(2(2)+2(0))+2+2(0)

输入格式

一行一个正整数 n n n

输出格式

符合约定的 n n n 0 , 2 0, 2 0,2 表示(在表示中不能有空格)。

样例 #1

样例输入 #1

1315

样例输出 #1

2(2(2+2(0))+2)+2(2(2+2(0)))+2(2(2)+2(0))+2+2(0)

提示

【数据范围】

对于 100 % 100\% 100% 的数据, 1 ≤ n ≤ 2 × 10 4 1 \le n \le 2 \times {10}^4 1n2×104

所需变量:
int i;//循环变量

int j;//循环变量

int num;//代表所需要求展开式的数

思路:我们首先要判断这个数是否能展开,如果能展开的情况下要考虑他后面是否还有数字能展开,如果能展开我们就要加括号(),将后面能展开的都括号起来!然后循环不断地调用递归!
所调用的递归代码如下:

int solution(int &num){
    int i,j;
    if(num == 1){
        cout<<"2(0)";
    }else if(num == 2){
        cout<<"2";
    }else{
        i = 2;
         while(pow(2,i)<num){
             i++;
         }
         for(j = i;j>=0;j--){
             if(num>pow(2,j)){
                if(j == 1){
                	num -=pow(2,j);
				 	cout<<"2+";
				 }else{
				 	num -=pow(2,j);
                 	cout<<"2(";
				 	solution(j);
				 	cout<<")+";
				 }
             }else if(num == pow(2,j)){
             	if(num == 1){
             		num = 0;
             		cout<<"2(0)";
				 }else if(num == 2){
				 	num = 0;
				 	cout<<"2";
				 }else{
				 	num  = 0;
                 	cout<<"2(";
				 	solution(j);
				 	cout<<")";
				 }
             }
         }
    }
}

上面这个代码的递归过程和思路都是完全没有问题的,我也是思索了很久也没有找到错误所在!
后来发现我把j当成变量传入下次了,那么当j再下一次递归的时候被改变,那么我们返回回来之后,j就发生改变了!这不是我们想要的答案!,因此我们就该定义一个变量记录下当时的j。这样就不会出错了!

正确代码在下面!
错误示范

#include<iostream>
using namespace std;
#include<math.h>
int solution(int &num){
    int i,j;
    if(num == 1){
        cout<<"2(0)";
    }else if(num == 2){
        cout<<"2";
    }else{
        i = 2;
         while(pow(2,i)<num){
             i++;
         }
         for(j = i;j>=0;j--){
             if(num>pow(2,j)){
                if(j == 1){
                	num -=pow(2,j);
				 	cout<<"2+";
				 }else{
				 	num -=pow(2,j);
                 	cout<<"2(";
				 	solution(j);
				 	cout<<")+";
				 }
             }else if(num == pow(2,j)){
             	if(num == 1){
             		num = 0;
             		cout<<"2(0)";
				 }else if(num == 2){
				 	num = 0;
				 	cout<<"2";
				 }else{
				 	num  = 0;
                 	cout<<"2(";
				 	solution(j);
				 	cout<<")";
				 }
             }
         }
    }
}
int main(){
    int num;
    cin>>num;
    solution(num);
    return 0;
}

完整代码如下(编译器是dev,语言是C语言):
正确答案:

#include<iostream>
using namespace std;
#include<math.h>
int solution(int &num){
    int i,j;
    if(num == 1){
        cout<<"2(0)";
    }else if(num == 2){
        cout<<"2";
    }else{
        i = 2;
         while(pow(2,i)<num){
             i++;
         }
         for(j = i;j>=0;j--){
             if(num>pow(2,j)){
                if(j == 1){
                	num -=pow(2,j);
				 	cout<<"2+";
				 }else{
				 	num -=pow(2,j);
                 	cout<<"2(";
                 	int t = j;
				 	solution(j);
				 	j = t;
				 	cout<<")+";
				 }
             }else if(num == pow(2,j)){
             	if(num == 1){
             		num = 0;
             		cout<<"2(0)";
				 }else if(num == 2){
				 	num = 0;
				 	cout<<"2";
				 }else{
				 	num  = 0;
                 	cout<<"2(";
				 	int t = j;
				 	solution(j);
				 	j = t;
				 	cout<<")";
				 }
             }         }
    }
}
int main(){
    int num;
    cin>>num;
    solution(num);
    return 0;
}

在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值