紫書例題p245
Piotr found a magical box in heaven. Its magic power is that if you place any red balloon inside it then, after one hour, it will multiply to form 3 red and 1 blue colored balloons. Then in the next hour, each of the red balloons will multiply in the same fashion, but the blue one will multiply to form 4 blue balloons. This trend will continue indefinitely.
The arrangements of the balloons after the 0-th, 1-st, 2-nd and 3-rd hour are depicted in the following diagram.
As you can see, a red balloon in the cell (i, j) (that is i-th row and j-th column) will multiply to produce 3 red balloons in the cells (i ∗ 2 − 1, j ∗ 2 − 1), (i ∗ 2 − 1, j ∗ 2), (i ∗ 2, j ∗ 2 − 1) and a blue balloon in the cell (i ∗ 2, j ∗ 2). Whereas, a blue balloon in the cell (i, j) will multiply to produce 4 blue balloons in the cells (i ∗ 2 − 1, j ∗ 2 − 1), (i ∗ 2 − 1, j ∗ 2), (i ∗ 2, j ∗ 2 − 1) and (i ∗ 2, j ∗ 2). The grid size doubles (in both the direction) after every hour in order to accommodate the extra balloons. In this problem, Piotr is only interested in the count of the red balloons; more specifically, he would like to know the total number of red balloons in all the rows from A to B after K-th hour.
Input
The first line of input is an integer T (T < 1000) that indicates the number of test cases. Each case contains 3 integers K, A and B. The meanings of these variables are mentioned above. K will be in the range [0, 30] and 1 ≤ A ≤ B ≤ 2 K.
Output
For each case, output the case number followed by the total number of red balloons in rows [A, B] after K-th hour.
Sample Input
3
0 1 1
3 1 8
3 3 7
Sample Output
Case 1: 1
Case 2: 27
Case 3: 14
題意:一開始有一個紅氣球,每小時,一個紅氣球會變成3個紅氣球和1個藍氣球,而一個藍氣球會變成4個藍氣球,如圖所示,經三小時變化後。
根據圖中給出的氣球的分裂方式,求第K次分裂後,第A行到第B行的紅色氣球的數量。
可以這麼想,用前B行的紅色氣球的數量減去A-1行的紅色球的數量就可以得到第A行到第B行的紅色氣球的數量。
然後再觀察第三小時和第二小時的圖,發現第二小時的圖和第三張圖分成四塊後的其中三塊相同,而不相同的一塊全是藍色,不需要計算。
假設函數f(k,i)表示第k小時,前i行的所有紅球個數,則問題的答案就是f(k,B)-f(k,A-1)。f(k,i)的求解需要根據i與2的(k-1)次方的大小分類討論,遞歸求解。
#include<cstring> #include<cstdio> #include<iostream> using namespace std; int T,k,a,b; long long c[35]; long long f(int k, int i) { if(!i) return 0; if(!k) return 1; if(i<1<<(k-1)) return 2*f(k-1,i); else return f(k-1,i-(1<<(k-1)))+2*c[k-1]; 1<<(k-1)=2的k-1次方 } int main() { c[0]=1; for(int i=1;i<30; i++) c[i]=3*c[i-1]; cin>>T; for(int s=1;s<=T; s++) { cin>>k>>a>>b; long long total=f(k,b)-f(k,a-1); printf("Case %d: %lld\n",s,total); } return 0; }