[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 1≤n≤2×104。
解题思路
题目给出数据范围为[1,20000],其中小于2000的2的最高次是14,所以指数的范围为2的[0,14]。
先看题目的例子
137 = 2(7)+2(3)+2(0),
- 令n等于137,我们可以从 2 14 2^{14} 214开始枚举,直到找到一个可能的最大的可以被n这个数减的数,可以找到 2 7 2^7 27,然后把7放入结果数组。 n = n − n=n- n=n− 2 14 2^{14} 214,也就是9
- n=9时,此时我们可以从上一次的最高次幂7开始枚举,可以找到 2 3 2^3 23可以被n减, n = n − 2 3 n=n-2^3 n=n−23,把3放入结果数组,n=1;
- n=1时,直接把2(0)放入结果数组。
-
关于如何处理第一步算出来的指数,我们直接采用递归的方式,把第一步算出来的指数再重新传入函数中,对这个数重新被2的次幂分割即可。
-
关于递归的括号怎么加。通过对题目给的1315的样例的观察,我们发现最底层的括号里,也就是加号之间,只有三种可能 2 ( 0 ) 2(0) 2(0), 2 2 2,2(2),所以我们在递归函数中,发现求到的可能最大的指数为 0,1,2时,直接分别返回 2 ( 0 ) 2(0) 2(0), 2 2 2,2(2)即可。如果不为这三种可能,就继续递归。我们在函数传参的过程中传入一个flag=0,表示当前位为本层括号里面的第一个数,那么这个数之前不能有 + ,否则就在前面加一个 +。
3.对于求可能的最大指数的优化。采用二分查找思想,查找满足条件 2 x 2^x 2x不大于n的最大的可能x。(这里的思想和找一个小于n的最大的数的思想一致)。
代码如下
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
const int maxe = 14;
int binSearch(int l, int h, int n) {
int re;
while (l <= h) {
int mid = (l + h) / 2;
if (pow(2, mid) <= n) {
re = mid;
l = mid + 1;
}
else {
h = mid - 1;
}
}
return re;
}
string func(int n,int flag) {
string re;
while (n > 0) {
if (flag == 1)
re += "+";
int tmpmax = 0;
if (n > 1) {
tmpmax = binSearch(0, maxe, n);
n = n - pow(2, tmpmax);
}
else {//n==1时,n=2^0;
n--;
}
if (tmpmax == 0) {
re += "2(0)";
}
else if (tmpmax == 1) {
re += "2";
}
else if (tmpmax == 2) {
re += "2(2)";
}
else re += "2("+func(tmpmax,0)+")";
flag = 1;
}
return re;
}
int main() {
int n;
cin >> n;
string re=func(n,0);
cout << re;
}
写在最后
一次过,欧耶!!!感觉自己对于递归的理解又深了一点点。