這題一開始是想用遞迴的方法解決,就是定義乙個全域性變數來計數,然後通過題中該自然數不能超過原數一半的條件來結束呼叫,但是該方法時間複雜度過大,會超時,**如下:
#includeint s=1;
void sum(int n)
}int main()
本題可以從另乙個角度切入,由於本題是對輸入的數用相同的方法進行處理而且n較小,可以考慮是否可以用數學的方法去尋找相鄰項的遞推關係,然後用迴圈跑一遍就可以解決,所以可以先列舉前幾項來找找規律:
a[1]=1;可以發現a[2n]=a[2n+1],而隔項看可以找到遞推的規律:a[2]=2;a[3]=2;
a[4]=4;a[5]=4;
a[6]=6;a[7]=6;
a[8]=10;a[9]=10;
a[1]=1;這個可以用兩重迴圈來模擬,一重做遍歷,一重做累加。最後只要通過下標就能找到需要的值a[2]=a[1]+1;
a[3]=a[1]+1;
a[4]=a[1]+a[2]+1;
a[5]=a[1]+a[2]+1;
a[i]=a[1]+a[2]+···+a[i/2]+1;(i為整數)
ps.洛谷大佬題解
有些還看不太懂所以先碼著
按一定的規律對數值進行處理或用遞迴能解但較複雜的題目可以考慮是否可以用遞推法求解
在實現這題時,我覺得難點主要是在於如何實現對於列舉選數的模擬,因為存在陣列中的數順序是固定的,而抽取其中一定數作累加這個過程是隨機的,這就給模擬增加了思維上的難度。
然而只要認識到從右往左抽取可以使過程相對固定(不用對陣列進行處理只要改變長度就行),就使模擬難度降低。
而從右往左不斷抽取的過程是類似的,實現上也與漢諾塔問題很相似(呼叫函式的同時規模不斷減小),所以可以考慮到需要用到遞迴的方法。
**如下:
#includeint a[5000001];
int s=0;
void ans(int sum) }}
int main(){
int n,k,i;
scanf("%d %d",&n,&k);
for(i=0;i如果發現在實現時有某個過程在不斷重複但是規模卻在不斷增大或減少,可以考慮用遞迴來實現。
函式遞迴總結
函式的遞迴 例1.接收乙個整型值,並且按順序列印他的每一位.例如 輸入 1234.輸出 1 2 3 4 include include void print int num printf d n num 10 intmain 執行結果 例2.求字串的長度 法1.利用strlen函式直接求 inclu...
函式的遞迴總結
函式的遞迴總結 概念 程式呼叫自身的程式設計技巧稱為遞迴 思考方式 在於在於將大事化小 遞迴的兩個條件 1.有限制條件,當滿足這個限制條件時,遞迴便不再進行。2.每次遞迴呼叫後越來越接近限制條件,讓程式得以執行結束。使用遞迴必須要明白 1.明確這個函式要完成那些東西。2.尋找遞迴要結束的條件。3.找...
遞迴與尾遞迴總結
編者按 尾遞迴最大的好處就是不需要儲存當前函式的現場,在彙編級別即不需要call和set了 1 遞迴 關於遞迴的概念,我們都不陌生。簡單的來說遞迴就是乙個函式直接或間接地呼叫自身,是為直接或間接遞迴。一般來說,遞迴需要有邊界條件 遞迴前進段和遞迴返回段。當邊界條件不滿足時,遞迴前進 當邊界條件滿足時...