CSU-ACM2017暑期训练3-递推与递归I - Erratic Expansion UVA - 12627

题目

实在是不会找规律啊,也是看的题解,首先可以发现每过一分钟,左上角,右上角,左下角的图形和前一分钟的图形相同,

那么对于第K分钟的第A行到第B行的红球数量可以表示为,第K分钟时,前B行的红球总数减去第A-1行的红球总数。

那么问题就转化为了求第i分钟,前j行的红球总数,这时候我们还可以发现,对于第i分钟的前2^i行,其红球个数为3^i个,

那么我们可以对这个j进行分类讨论,由于是第i分钟,为了简化问题,我们对于第2^(i - 1)行进行分界,

若j>= 2^(i - 1),那么红球个数应该是2 * 3^(i - 1) + 第i - 1分钟,前j - 2 ^ (i - 1)行的红球个数,

解释一下为什么会是2乘以 3^(i - 1),这是因为前面2^(i - 1)行,包含了左上角和右上角的红球,

而这些红球个数为3^(i - 1)个,后面的j - 2^(i - 1),是由于其左下角和前一分钟的图形相同,j < 2^(i - 1)就简单了,

只要求第i - 1分钟,前 j行的红球个数即可。显然这需要递归求解,

代码如下:

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
long long a[35];
long long solve(int k,int i){
if(!i)
return 0;
if(!k)
return 1;
int x = 1<<(k - 1);
if(i < x)
return 2 * solve(k - 1,i);
else
return 2 * a[k - 1] + solve(k - 1,i - x);
}
int main(){
a[0] = 1;
for(int i = 1;i <= 30;i++)
a[i] = a[i - 1] * 3;
int T,t = 0;
cin >> T;
while(T--){
int K,A,B;
cin >> K >> A >> B;
cout << "Case " << ++t << ": " << solve(K,B) - solve(K,A - 1) << endl; 
}
return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值