1. 程式人生 > >UVA 12627(遞推&遞歸_H題)解題報告

UVA 12627(遞推&遞歸_H題)解題報告

get tdi 圖片 mat ble log gpo b- lin

題目鏈接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4352

--------------------------------------------------------------------------------------------------------------------------------------------------------------------

題意:氣球按照一定方式進行復制,要求給出數量。

思路:

根據題目提示,這道題可以用f(k,i)表示k小時後最上邊i行的紅氣球總數那麽我們的答案就可以表示為f(k,b)-f(k,a-1)這裏我們通過觀察,在k小時後所分成的四部分氣球中,最右下角區域的氣球是跟其他區域氣球不相同的。因此我們可以分成兩種情況(i在上半部分和i在下半部分):

當i<2^(k-1),f(k,i)=2*f(k-1,i)

當i>=2^(k-1),f(k,i)=c(k-1)+f(k-1,i-2^(k-1))

其中c(k-1)代表完整的那部分的紅氣球數,也就是k-1小時後的紅氣球數。

由氣球構造方式可得遞推式:c(k)=3c(k-1),c(0)=1,可知這是個等比數列,求得c(k)=3^k。

同理,我們也可以利用g(k,i)表示k小時後最下邊i行的紅氣球總數,將答案用g(k,i)表示出來。

代碼:

技術分享圖片
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<stack>
#include<bitset>
#include<cstdlib>
#include<cmath>
#include<set
> #include<list> #include<deque> #include<map> #include<queue> using namespace std; typedef long long ll; const double PI = acos(-1.0); const double eps = 1e-6; ll c[30]={1}; ll ballon(ll K,ll i){ if(i<=0) return 0; if(K==0) return 1; if(i<=pow(2,K-1)) return 2*ballon(K-1,i); else return 2*c[K-1]+ballon(K-1,i-pow(2,K-1)); } int main(void){ for(int p=1;p<=30;p++){ c[p]=c[p-1]*3; } int T=0; scanf("%d",&T); int count =1; //freopen("out.txt","wa",stdout); for(int i=0;i<T;i++){ ll K,A,B; scanf("%lld %lld %lld",&K,&A,&B); printf("Case %d: %lld\n",count,ballon(K,B)-ballon(K,A-1)); count++; } return 0; }
View Code

UVA 12627(遞推&遞歸_H題)解題報告