CSU-ACM2017暑期训练3-递推与递归I

来源:互联网 发布:js object添加元素 编辑:程序博客网 时间:2024/06/05 05:59

题目

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

那么对于第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;
}

原创粉丝点击