首先,很容易看出这是一道递归与分治方面的题目 (标签上有) 。
那么先看样例137
137 可表示为 2(7)+2(3)+2(0)
7=2(2)+2(1)+2(0)
3=2(1)+2(0)
所以最后 137可表示为
2(2(2)+2(1)+2(0))+2(2(1)+2(0))+2(0)
这里和样例的表示不太相同,我们之后再说。
那么我们分析一下这个思路原理。
首先是找到第一个比137小的2次幂,也就是2的7次方,之后对7做相同的处理,直至完全有2和0表示出来。然后用137-27=9,找到第一个比9小的2次幂,也就是2的3次方,对3进行相同的处理…依此类推,直至化为0。
这就是我们的递归思路,但要注意:题目中要求的是21写成2,20写成2(0),这里在写递归函数是要特判。此外,是否输出加号在于原数减去2m后是否为0。
代码如下:
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
int a[16];
void show(int n) {
// 从大到小遍历
for (int i = 15; i >= 0; i--) {
// 如果找到了第一个比n小的数
if (a[i] <= n) {
// 特判,i==1时直接输出2
if (i == 1)
cout << 2;
// 特判,i==0时直接输出2(0)
else if (i == 0)
cout << "2(0)";
// 否则我们先输出2(
else {
cout << "2(";
// 递归处理i
show(i);
// 输出)
cout << ")";
}
// n减去a[i]
n -= a[i];
// 如果n不等于0,就输出加号
if (n != 0)
cout << "+";
}
}
}
int main()
{
ios_base::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int n;
cin >> n;
a[0] = 1;
// 预处理,a要储存2^0至2^15次方的所有值
for (int i = 1; i < 16; i++)
a[i] = 2 * a[i - 1];
show(n);
return 0;
}
我在看题解的时候发现有位大佬用位运算做,其实核心思路是一样的,但是应该会比这种方法快一些。
如果有帮助还请小伙伴们点个赞哦~