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)-f(k,a-1)

如何求f(k,i)?

这里我们通过观察,在k小时后所分成的四部分气球中,最右下角区域的气球是跟其他区域气球不相同的。因此我们可以分成两种情况(i在上半部分和i在下半部分)。

当i<2^(k-1),f(k,i)=2*f(k-1,i)

当i>=2^(k-1),f(k,i)=c(k-1)+f(k-1,i-2^(k-1))

其中c(k-1)代表完整的那部分的红气球数,也就是k-1小时后的红气球数。

由气球构造方式可得递推式:c(k)=3c(k-1),c(0)=1,可知这是个等比数列,求得c(k)=3^k

至此我们就可以得到我们想要的答案了。

第一次,时间超限:

#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
long f(long k,long h)
{
	if(k==0&&h==1) return 1;
	if(h<=0) return 0;
	long m=pow(2,k-1);
	if(h>m) return 2*f(k-1,m)+f(k-1,h-m);
	else return 2*f(k-1,h);
}
int main()
{
	int T,i,q=1;
	cin>>T;
	while(T--)
	{
		long k,A,B,sum=0;
		cin>>k>>A>>B;
		printf("Case %d: ",q++);
		cout<<f(k,B)-f(k,A-1)<<"\n";
	}
	return 0;
}

第二次,根据书本改了下,加了个c函数,对了

#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
long c(long k)
{
	long sum=1;
	while(k--)
	{
		sum*=3;
	}
	return sum;
}
long f(long k,long h)
{
	if(k==0&&h==1) return 1;
	if(h<=0) return 0;
	long m=pow(2,k-1);
	if(h>m) return 2*c(k-1)+f(k-1,h-m);
	else return 2*f(k-1,h);
}
int main()
{
	int T,i,q=1;
	cin>>T;
	while(T--)
	{
		long k,A,B,sum=0;
		cin>>k>>A>>B;
		printf("Case %d: ",q++);
		cout<<f(k,B)-f(k,A-1)<<"\n";
	}
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值