题意:开始有1个红气球,每小时后1个红气球会变为3个红气球和1个蓝气球,问k小时后第A行到第B行的气球数。
解:用g(k,i)表示第k小时时,从底部数i行的红气球数。所以ans = g(k,2^k-A+1) - g(k,2^k -B)
k小时情况由4个k-1小时时的情况组成由k1,k2,k3,k4表示
如果i所求的区域包含k1,k2,由于k4部分全部是蓝气球,所以求得是2*(k1中在区域中的) + k3
即 i >= 2^(k-1),则 g(k,i) = 2 * g(k-1,i-2 ^ (k-1)) + c(i);其他则g(k,i) = g(k-1,i);
其中c(0) = 1,c(i) = 3*c(i-1);
#include <iostream> #include <cstdio> #include <cmath> #include <cstring> #include <algorithm> #include <cstdlib> #include <stack> #include <cctype> #include <string> #include <malloc.h> #include <queue> #include <map> #include <set> using namespace std; const int INF = 0xffffff; const double esp = 10e-8; const double Pi = 4 * atan(1.0); const int maxn = 100001 + 10; const long long mod = 1000000007; const int dr[] = {1,0,-1,0,-1,1,-1,1}; const int dc[] = {0,1,0,-1,1,-1,-1,1}; typedef long long LL; LL gac(LL a,LL b){ return b?gac(b,a%b):a; } long long g(int k,int i){ if(k == 0){ if(i >= 1) return 1; else return 0; } if(i >= 1 << (k-1)){ long long c = pow(3,k-1)+esp; return 2* g(k-1,i- (1<< (k-1))) + c; } else{ return g(k-1,i); } } int main() { #ifndef ONLINE_JUDGE freopen("inpt.txt","r",stdin); // freopen("output.txt","w",stdout); #endif int t; scanf("%d",&t); for(int cas = 1;cas <= t;cas++){ int A,B,k; scanf("%d%d%d",&k,&A,&B); long long tmp = 1 << k; long long a = g(k,tmp-A+1); long long b = g(k,tmp-B); printf("Case %d: %lld\n",cas,a-b); } return 0; }
时间: 2024-10-27 03:15:56