• P1010 幂次方


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

    于是我就开始尝试用递归写,第一次写的简直一塌糊涂:

    #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; }

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

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

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

    我经过调试发现:

    因为前面我们让ans++了,所以他到后面怎么也不可能=0。

    可以说是强制让他+1了,因为这个hh在乘2的时候很有可能已经大于a了(可能你会问不是上一次循环的时候已经判断了吗,但是如果我告诉你这是第一次循环呢),那么我们在判断的时候hh已经大于a了,乘二不就更加大于a了吗?

    出大问题

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

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

    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。

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

  • 相关阅读:
    左耳听风-ARTS-第4周(2019/4/21-2019/4/27)
    Java集合总结
    Zuul网关总结
    左耳听风-ARTS-第3周(2019/4/7-2019/4/13)
    左耳听风-ARTS-第2周(2019/3/31-2019/4/6)
    Java泛型相关总结(下)
    左耳听风-ARTS-第1周
    去长江边走走,看看
    第1记
    c#发送邮件
  • 原文地址:https://www.cnblogs.com/dgdger/p/12885376.html
Copyright © 2020-2023  润新知