UVA 12627 递归

https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4352

题目复制不过来,我把主要部分拍过来。

题目大意:求k时刻,从A行到B行的所有红色气球数。(闭区间[A,B])

思路:感觉这道题很好的诠释了递归。首先我们观察一波图形,规律性极强。(1)k时刻的红色气球数时k-1时刻的红色气球数的三倍。(2)k时刻从第一行到第2^(k-1)行的红色气球数是k-1时刻红色气球数的两倍。(3)k时刻从第2^(k-1)+1行到第2^k行的红色气球数等于k-1时刻从第一行到第2^(k-1)行的红色气球数。因此我们可以预先用数组存储k时刻的所有红色气球数。直接求从A行到B行的红色气球不好算,我们先求从第一行到第B行的气球数,然后再求从第一行到第A-1行的红色气球数,二者之差就是答案。怎么计算呢?递归的计算。我们设行编号为i,num[k]表示k时刻的红色气球数,f(k,i)表示k时刻从第一行到第i行的红色气球数。来看一下k时刻红色气球数与行编号的关系:(1)若i==2^k,那么红色气球数为num[k]。(2)若2^(k-1)<i<2^k,那么红色气球数为f(k-1,i-2(k-1))+2*num[k-1]。(3)若i==2^(k-1),那么红色气球数为2*num[k-1]。(4)若0<i<2^(k-1),那么红色气球数为f(k-1,i)。(5)若i=0,则红色气球数为0。综上,我们就可以递归的计算红色气球数了。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<set>
#include<algorithm>
#include<iterator>
#define INF 0x3f3f3f3f
typedef long long ll;
typedef unsigned long long ull;
using namespace std;

ll f(int k,ll t);
ll num[35];


int main()
{
	num[0]=1;
	for(int i=1;i<=30;i++)
		num[i]=num[i-1]*3;
	int t;
	scanf("%d",&t);
	int k;
	ll a,b;
	int time=0;
	while(t--)
	{
		scanf("%d%lld%lld",&k,&a,&b);
		printf("Case %d: %lld\n",++time,f(k,b)-f(k,a-1));
	}
	return 0;
}

ll f(int k,ll t)
{
	if(t==0)
		return 0;
	if(k==0)
		return 1;
	if(t==(1<<k))
		return num[k];
	else if(t>(1<<(k-1)))
		return f(k-1,t-(1<<(k-1)))+2*num[k-1];
	else if(t==(1<<(k-1)))
		return 2*num[k-1];
	else
		return 2*f(k-1,t);
}

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值