不难发现,每过一个小时,除了右下方的气球全都是蓝色以外,其他都和上一个小时的气球是一样的,所以是可以递推的。然后定义一类似个前缀和的东西f(k,i)表示k小时之后上面i行的红气球数。预处理出k小时的红气球总数c(k),递归时候注意终止条件。
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 31; ll c[maxn]; ll f(int k,int i) { if(!i) return 0; if(i == (1<<k)) return c[k]; int tot = 1<<(k-1); if(i>tot) return f(k-1,i-tot)+(c[k-1]<<1); else return f(k-1,i)<<1; } int main() { int T; scanf("%d",&T); c[0] = 1; for(int i = 1; i < maxn; i++) c[i] = c[i-1]*3; int kas = 0; while(T--){ int k,a,b; scanf("%d%d%d",&k,&a,&b); ll ans = f(k,b)-f(k,a-1); printf("Case %d: %lld ",++kas,ans); } }