uva 12627

题意:开始有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
",cas,a-b);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/hanbinggan/p/4309196.html