UVA 12673 Erratic Expansion 奇怪的气球膨胀

不难发现,每过一个小时,除了右下方的气球全都是蓝色以外,其他都和上一个小时的气球是一样的,所以是可以递推的。然后定义一类似个前缀和的东西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\n",++kas,ans);
    }
}
时间: 2024-08-02 06:53:38

UVA 12673 Erratic Expansion 奇怪的气球膨胀的相关文章

UVA - 12627 Erratic Expansion 奇怪的气球膨胀 (分治)

紫书例题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 multip

uva 12627 - Erratic Expansion(递归求解)

递归的边界条件写的多了--没必要写呢么多的.. 不明白可共同探讨~ #include<cstdio> #include<iostream> #include<cmath> using namespace std; long long dp(int kk,int pos) { int n=kk;int temp=(int)pow(2,n); // printf("%d %d\n",kk,pos); if(kk==0&&pos==1) r

UVA - 12627 Erratic Expansion(奇怪的气球膨胀)(递归)

题意:问k小时后,第A~B行一共有多少个红气球. 分析:观察图可发现,k小时后,图中最下面cur行的红气球个数满足下式: (1)当cur <= POW[k - 1]时, dfs(k, cur) = dfs(k - 1, cur); (2)当cur > POW[k - 1]时, dfs(k - 1, cur) = 2 * dfs(k - 1, cur - POW[k - 1]) + tot[k - 1]; 其中,POW[k - 1]为2^(k  - 1),tot[k - 1]为k-1小时后图中的

UVa 12627 奇怪的气球膨胀(分治)

https://vjudge.net/problem/UVA-12627 题意:一开始有一个红气球.每小时后,一个红气球会变成3个红气球和1个蓝气球,而1个蓝气球会变成4个蓝气球.如图所示分别是经过0,1,2,3,小时后得情况.经过k小时后,第A~B行一共有多少个红气球. 思路:由图分析,每次把图分为四个部分,右下角的部分全为蓝气球,不用去管他,剩下三部分都是一样的并且和前一小时的图形是一样的,这样的话我们可以计算出每个时刻红气球的总数. 既然每次可以分为四部分,那么很明显的就是用分治法来解决.

(白书训练计划)UVa 12627 Erratic Expansion(递归+找规律)

题目地址:UVa 12627 这题是先找规律,规律在于对于第k个小时的来说,总是可以分成右下角全是蓝色气球,右上角,左下角与左上角三个一模一样的k-1个小时的气球.这样的话,规律就很清晰了,然后用递归做比较方便... 代码如下: #include <iostream> #include <cstdio> #include <string> #include <cstring> #include <stdlib.h> #include <ma

Uva 12627 Erratic Expansion(递归)

这道题大体意思是利用一种递归规则生成不同的气球,问在某两行之间有多少个红气球. 我拿到这个题,一开始想的是递归求解,但在如何递归求解的思路上我的方法是错误的.在研读了例题上给出的提示后豁然开朗(顺便吐槽一下算法竞赛第二版在这这道题目上(P246)提示写的有问题,g(k,i)=2g(k-1,i-2^(k-1))+c(k-1)  ,他把c(k-1)写成了c(k)...我纠结这个纠结了好久) 根据题目提示,这道题可以用f(k,i)表示k小时后最上边i行的红气球总数 那么我们的答案就可以表示为f(k,b

UVA 12627 Erratic Expansion

#include<bits/stdc++.h> #define REP(i,a,b) for(int i=a;i<=b;i++) #define MS0(a) memset(a,0,sizeof(a)) using namespace std; typedef long long ll; const int maxn=1000100; const int INF=1<<29; ll k,a,b; ll s[maxn]; ll f(ll i,ll k) { if(i==0) r

(记忆化+暴力)UVA - 12627 Erratic Expansion

题意:一个数列,一开始只有一个1,进行k次操作,每次操作都把数列中原本的数全都翻倍然后追加在数列的后面,形成了一个全新的数列,输出全新数列中l到r的和. 分析:以上的题意是经过转化后的题意,变的非常简单,而不在卡在二维的思维中出不来. 可以看到如果在后半段,就等于前半段对应位置的两倍,可以从最高2^k个数的维护,k不断-1,最终变成维护数列中第一个1,直接返回1即可,形成了一个完美的递归. 1 ll dg(int u ,int d,int k) { 2 if(u==1&&d==1)retu

UVa 12627 (递归 计数 找规律) Erratic Expansion

直接说几个比较明显的规律吧. k个小时以后,红气球的个数为3k. 单独观察一行: 令f(r, k)为k个小时后第r行红气球的个数. 如果r为奇数,f(r, k) = f((r+1)/2, k-1) * 2 如果r为偶数,f(r, k) = f(r/2, k-1) 令g(r, k)为k个小时后前r行红气球的个数. 如果r为偶数,g(r, k) = g(r/2, k-1) * 3; 如果r为奇数,g(r, k) = g(r-1, k) + f(r, k); 因此f和g都可以用递归求解. 1 #inc