當初在學遞迴的結構時,一直對於遞迴該怎麼用很是不解。所以想藉由這篇文章做些練習讓我能更熟悉遞迴怎麼用。

b911 我想跟Kevin借筷子系列4

這題可以用DP的概念去解,假設Kevin有7隻筷子1 2 3 4 5 6 7,先砍4,剩下1 2 3 0 1 2 3,而1 2 3又是另外一個問題。這正是DP的用小問題去推出大問題 的精神。

AC (4ms, 316KB)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include<iostream>
using namespace std;

long long cut(long long n){
if(n==2){return 2;}
else if(n==1){return 1;}
return cut(n/2)+1;
}

int main(){
long long n;
while(cin>>n){
cout<<cut(n)<<endl;
}
return 0;
}

在解的過程中,我發現了一個規律。當有1根筷子,只需切1次。當有2~3根筷子,需切2次。當有4~7根筷子,需切3次。也就是筷子的數量和切的次數有log2的關係。

AC (4ms, 344KB)

1
2
3
4
5
6
7
8
9
10
11
#include<iostream>
#include<cmath>
using namespace std;

int main(){
long long n;
while(cin>>n){
cout<<(int)log2(n)+1<<endl;
}
return 0;
}

c002. 10696 - f91

在建表的時候發現了一個神奇的規律,這是我建表時寫的code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include<stdio.h>
#include<time.h>

int f91(int n){
if(n<=100){
return f91(f91(n+11));
}
return n-10;
}

int main(){
clock_t start,end;
start = clock();
int i;
for(i=0;i<=100;i++){
if(i%5==0 && i!=0){printf("\n");}
printf("f(%3d) =%3d ",i,f91(i));
}
end = clock();
double diff = end-start;
printf("\n共花%lfs\n",diff / CLOCKS_PER_SEC);
return 0;
}

這是輸出結果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
f(  0) = 91 f(  1) = 91 f(  2) = 91 f(  3) = 91 f(  4) = 91 
f( 5) = 91 f( 6) = 91 f( 7) = 91 f( 8) = 91 f( 9) = 91
f( 10) = 91 f( 11) = 91 f( 12) = 91 f( 13) = 91 f( 14) = 91
f( 15) = 91 f( 16) = 91 f( 17) = 91 f( 18) = 91 f( 19) = 91
f( 20) = 91 f( 21) = 91 f( 22) = 91 f( 23) = 91 f( 24) = 91
f( 25) = 91 f( 26) = 91 f( 27) = 91 f( 28) = 91 f( 29) = 91
f( 30) = 91 f( 31) = 91 f( 32) = 91 f( 33) = 91 f( 34) = 91
f( 35) = 91 f( 36) = 91 f( 37) = 91 f( 38) = 91 f( 39) = 91
f( 40) = 91 f( 41) = 91 f( 42) = 91 f( 43) = 91 f( 44) = 91
f( 45) = 91 f( 46) = 91 f( 47) = 91 f( 48) = 91 f( 49) = 91
f( 50) = 91 f( 51) = 91 f( 52) = 91 f( 53) = 91 f( 54) = 91
f( 55) = 91 f( 56) = 91 f( 57) = 91 f( 58) = 91 f( 59) = 91
f( 60) = 91 f( 61) = 91 f( 62) = 91 f( 63) = 91 f( 64) = 91
f( 65) = 91 f( 66) = 91 f( 67) = 91 f( 68) = 91 f( 69) = 91
f( 70) = 91 f( 71) = 91 f( 72) = 91 f( 73) = 91 f( 74) = 91
f( 75) = 91 f( 76) = 91 f( 77) = 91 f( 78) = 91 f( 79) = 91
f( 80) = 91 f( 81) = 91 f( 82) = 91 f( 83) = 91 f( 84) = 91
f( 85) = 91 f( 86) = 91 f( 87) = 91 f( 88) = 91 f( 89) = 91
f( 90) = 91 f( 91) = 91 f( 92) = 91 f( 93) = 91 f( 94) = 91
f( 95) = 91 f( 96) = 91 f( 97) = 91 f( 98) = 91 f( 99) = 91
f(100) = 91
共花0.000229s

只要輸入的n<=100,無論n是多少,最後的結果都是91 !這下好辦了,只需要判斷輸入的n的大小,如果>100就輸出n-10,<=100就輸出91。這題要建表應該也沒問題,畢竟真的從0算到100也只花0.0002秒 ,只不過不建的話,程式碼就可以非常精簡。

AC (2ms, 76KB)

1
2
3
4
5
6
7
8
9
10
#include<stdio.h>

int main(){
int n;
while(scanf("%d",&n) && n){
if(n<=100){printf("f91(%d) = 91\n",n);}
else{printf("f91(%d) = %d\n",n,n-10);}
}
return 0;
}

封面圖源:AcFun