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。

以上僅是我的對於這道題的所有思路與想法,若是有什麼不對的地方,還請各位大佬及時向我糾正。

相關文章
相關標籤/搜索