关于 幂次方 一题的思路+代码(递归)

题目来源:洛谷 P1010 [NOIP1998 普及组] 幂次方

题目描述

任何一个正整数都可以用2的幂次方表示。例如
137=27+23+20
由此可知,137可表示为:
2(7)+2(3)+2(0)
而7又可以表示为:2(2)+2+2(0)
3可以表示为:2+2(0)
因此137最终表示为:
2(2(2)+2+2(0))+2(2+2(0))+2(0)

输入描述

一个正整数n(n≤20000)。

输出描述

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

输入样例1

1315

输出样例1

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

输入样例2

137

输出样例2

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

OP

\

思路

这道题要用递归来处理:

对于每一个大于2的数,都需要通过二进制将其拆为二的幂次和,对于每一个幂次再进行递归处理;

通过构建 tr[i] 来存储 i 的表达式;

通过处理二进制数和构建幂次栈来按顺序存储该数内含有2的哪些幂次,方便接下来的递归与构建字符串。

(对于(13)D,(1101)B,其幂次栈即为{3,2,0}\{3,2,0\},代表13=23+22+2113=2^3+2^2+2^1

还有一部分内容写在注释里了,方便理解。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

string tr[20004];//tr[i]存储i的表达式

string getst(int n)
{
if(tr[n][0])return tr[n];//如果构建过串,直接输出
stack<int>stk;//构建幂次栈
int c=0,z=n;//z为n的一个拷贝,用于二进制处理;c记录处理到的二进制位数
while(z)//构建幂次栈
{
if(z&1)stk.push(c);
c++;
z>>=1;
}
while(!stk.empty())
{
int z=stk.top();
stk.pop();
if(z!=1)//对于一般位,进行递归处理
{
tr[n]+="2(";
tr[n]+=getst(z);//递归
tr[n]+=')';
}
else tr[n]+='2';//如果n的二进制第1位为1,此时z=1,对字符串的贡献仅为‘2’
if(!stk.empty())tr[n]+='+';//如果不是最右位,就添一个‘+’
}
return tr[n];
}

int main()
{
tr[0]='0',tr[1]="1",tr[2]="2",tr[4]="2(2)";//初始化
int n;
cin>>n;
cout<<getst(n);
return 0;
}

初始化在函数外会RTE!

ED

\


关于 幂次方 一题的思路+代码(递归)
https://tanyuu.github.io/2021.01-06/关于 幂次方 一题的思路+代码(递归)/
作者
F Juny
发布于
2021年3月23日
许可协议