NOIP1998复赛:2的幂次方表示

2的幂次方表示

总时间限制:

1000ms

内存限制:

65536kB

描述

任何一个正整数都可以用2的幂次方表示。例如:
137=27+23+20
同时约定方次用括号来表示,即ab可表示为a(b)。由此可知,137可表示为:
2(7)+2(3)+2(0)
进一步:7=22+2+20(21用2表示)
3=2+20
所以最后137可表示为:
2(2(2)+2+2(0))+2(2+2(0))+2(0)
又如:
1315=210+28+25+2+1
所以1315最后可表示为:
2(2(2+2(0))+2)+2(2(2+2(0)))+2(2(2)+2(0))+2+2(0)

输入

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

输出

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

样例输入

137

样例输出

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

来源

NOIP1998复赛 普及组 第一题

我真的是觉得递归难想、难写,在参考了大神的代码后写出。
代码与解释:

#include
#include
using namespace std;
void Fun(int m);
int main(){
    int m;
    while(cin >> m){
        Fun(m);
        cout << endl;
    }
    return 0;
}
void Fun(int m){
    if(m == 2){          //特殊形式单独考虑,递归结束
        cout << "2";
        return;
    }
    if(m == 1){         //特殊形式单独考虑,递归结束
        cout << "2(0)";
        return;
    }
    int p = 1,n = 0;    //n记录幂次,p是一个数,尽量与m接近
    while(p <= m){      //使p与m最接近
        p *= 2;
        n++;           //最接近时的幂
    }
    if(m == p/2){        //m正好是一个2次幂,无需带+
        cout << "2(";
        Fun(n - 1);
        cout << ")";
    }
    else      //m不正好是一个二次幂,需要表示成多项
    {
        if(p/2==2)      //m是3时,一种特殊情况
        {
            cout << "2";
            cout << "+";
            Fun(m-p/2);   //可以直接写为Fun(1),因为这种情况本身就是m=3时才使用
        }
        else     //m不是3时的情况
        {
            cout << "2(";
            Fun(n - 1);
            cout << ")+";       //加另外的项
            Fun(m - p/2);       //将剩余的再递归求解
        }
    }
}

以上代码经OpenJudge判定通过。第43行改为注释里的形式OpenJudge也通过。