P1010 幂次方

这道题我一开始一点思路也没有,写了一个一团乱麻的代码,但后来越想越以为:哎,这题是递归啊ios

因而我就开始尝试用递归写,第一次写的简直一塌糊涂:函数

#include<iostream>
#include<cstdio>
using namespace std;
int n;
void dg(int a){//递归函数
    int hh=1,ans=0;//两个变量分别表明如今的次方值和如今运算了多少次
    while(a>0){
        hh*=2;
        ans++;
        if(hh*2>a){//判断次方值是否立刻就要超过a了
            a-=hh;//若是是那么a减去这个次方值
            if(ans==1){//若是如今这个只运算了一次,说明a里面最大能达到的就是2了,咱们就直接让他+2就行了(由于加号另输出,因此咱们直接输出2就好了)
                printf("2");
            }
            else if(ans==0){//若是这个只运算了零次,说明a能达到的最大值就是1(也就是a只剩一个1了),就直接输出2(0)就行了(由于无论什么数的0次方都是1,题目要求咱们输出的这个算式里面只能有0和2两个数字),不过咱们依然不用输出+号。
                printf("2(0)");
                return;
            }
            else{//若是当前运算次数既不等于1也不等于0,那就说明他最小是4,而4它又是由两个2组成的,这两个2都须要分别输出,因此咱们就再次调用函数。
                printf("2(");
                dg(ans);
                printf(")");
            }
            printf("+");//每次输出+号
            hh=1;//记得要把这些都初始化
            ans=0;
        }
    }
   return; }
int main(){ scanf("%d",&n); dg(n);//调用递归函数 return 0; }

虽然上面的注释都很正经的样子,但其实这个代码连样例都没过:spa

一个是加号问题,还有一个是他一次也没有判断到过ans=0这样的状况。3d

咱们先解决没有判断到过ans=0的这种状况(毕竟这个比较严重嘛),根源是什么呢?调试

我通过调试发现:code

由于前面咱们让ans++了,因此他到后面怎么也不可能=0。blog

能够说是强制让他+1了,由于这个hh在乘2的时候颇有可能已经大于a了(可能你会问不是上一次循环的时候已经判断了吗,可是若是我告诉你这是第一次循环呢),那么咱们在判断的时候hh已经大于a了,乘二不就更加大于a了吗?递归

出大问题

这直接致使a-=hh这一步的时候a变成了负数,后面的操做就会变得一团糟......io

那么咱们就要让他一步一判断,怎么实现呢?套一个while循环就行了:class

while(a>=hh*2){//由于他是在循环以前就判断的,因此咱们能够避免刚才说的强制+1的问题,甚至连后面的判断都省了,由于它就是一循环一判断(顺便说一下,他这个while能够顶刚才那个好几回循环)
    hh*=2;
    ans++;
}

你们会发现这样就方便不少,如今来解决刚才的那个加号问题:

if(a!=0){//加个判断就成了,由于a==0就算完了,加加号是多余的。
    printf("+");
}

这样这道题就作完啦,下面是完整代码:

#include<iostream>
#include<cstdio>
using namespace std;
int n;
void dg(int a){
    int hh=1,ans=0;//每次定义两个变量,意义前面说过了,大家知道就好。
    while(a>0){
        while(a>=hh*2){//这是用来拯救整个程序的while循环,用处我前面也说啦。
            hh*=2;
            ans++;
        }
        a-=hh;//a减去它里面能承受的最大的2的次方
        if(ans==0){//若是ans=0表明a最大的承受能力为2的0次方,也就是1,那么a也就确定=1(若是大的话ans就不可能=0了,而是会等于1或者更大)。
            printf("2(0)");
            return;
        }
        else if(ans==1){//若是ans=1表示a最大的承受能力为2的1次方也就是2,题目里面要求2的1次方后面就不加括号了,因此就直接输出2就好啦(通常ans=1的话,a就是2或者3)。
            printf("2");
        }
        else{//若是ans比0和1更大,那么a确定就大于3了(至少为4),而他题目要求只能输出0和2两种数字和括号,因此咱们把ans做为参数从新调用这个函数啦。
            printf("2(");
            dg(ans);
            printf(")");
        }
        if(a!=0) printf("+");//添加加号
        hh=1;
        ans=0;
    }
    return;//最后不要忘了return哦(虽然没有return也没事,可是我喜欢加上)
}
int main(){
    scanf("%d",&n);
    dg(n);
    return 0;
}

可能有的同窗会问:为何在ans=0的时候就return了,而在ans=1的时候就没有reutrn呢?

由于考虑到ans=1的时候可能会有2或者3两种状况,而咱们一一去判断会变得很麻烦,咱们干脆直接不加了,反正在while结束以后外面也会return。

以上仅是我的对于这道题的所有思路与想法,若是有什么不对的地方,还请各位大佬及时向我纠正。

相关文章
相关标签/搜索