大体题意不说了 书上画的很清楚= = !
思路:
令f(k,i)表示第k 小时后,从上面数i 行 红气球的个数,那么答案就是 f(k,b) - f (k,a-1);
通过看图不难发现:
如果i >= pow2(k-1) 那么 f (k,i) = 2 * C(k-1) + f (k-1, i - pow2( k-1 ) );
否则 f(k,i) = 2 * f (k-1,i);
其中C(k)表示k 小时后 红气球总数。 显然 C(k) = 3* C(k-1),在将C(0) = 1带入得: C(k) = pow3(k);
这样递归去算就可以了!
边界问题!
当k = 0 时 也就是0小时后 只有1个红气球 所以 k == 0 && i == 1 return 1;
当i == 0时,返回0.
注意long long
详细见代码:
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
int POW[32];
ll POW3[32];
void init(){
POW[0] = 1;
POW3[0] = 1;
for (int i = 1; i <= 30; ++i)POW[i] = POW[i-1] * 2;
for (int i = 1; i <= 30; ++i)POW3[i] = POW3[i-1]*3;
}
ll C(int k){
return POW3[k];
}
ll dfs(int k,ll i){
if (k == 0 && i == 1)return 1;
if (i == 0)return 0;
if (i >= POW[k-1])return (ll)2*C(k-1) + dfs(k-1,i-POW[k-1]);
return (ll)2*dfs(k-1,i);
}
int k,a,b;
ll solve(){
ll l = dfs(k,a-1);
ll r = dfs(k,b);
// printf("%lld %lld\n",l,r);
return r-l;
}
int main(){
int T,cnt=0;
init();
// printf("%d\n",POW[30]);
scanf("%d",&T);
while(T--){
scanf("%d %d %d",&k,&a,&b);
printf("Case %d: %lld\n",++cnt,solve());
}
return 0;
}
/*
1073741824
*/