仔细分析,变化过程,才可以写出递归函数。
如果当前行x是奇数行,那么其红气球数目是前一个小时第(x+1)>>1行 的2倍。
如果当前行x是偶数行,那么其红气球数目是前一个小时第(x+1)>>1行 的1倍。
/**==========================================
* This is a solution for ACM/ICPC problem
*
* @source:uva 12627 Erratic Expansion
* @type: 递归
* @author: wust_ysk
* @blog: http://blog.csdn.net/yskyskyer123
* @email: 2530094312@qq.com
*===========================================*/
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long ll;
const int INF =0x3f3f3f3f;
const int maxk=30;
int kase=0;
int fac[maxk+5];
void pre()
{
fac[0]=1;
for(int i=1;i<=maxk;i++)
{
fac[i]=fac[i-1]*2;
}
}
ll cal(int step,int k)
{
if(step==0) return 1;
return k%2? 2*cal(step-1,(k+1)>>1) : cal(step-1,(k+1)>>1) ;
}
ll work(int step,int up,int down)
{
if(!step)
{
return 1;
}
ll ans=0;
if(up%2==0)
{
up--;
ans-=cal(step,up);
}
if(down%2)
{
down++;
ans-=cal(step,down);
}
ans+=3*work(step-1,(up+1)>>1, (down+1)>>1 );
return ans;
}
int main()
{
pre();
int T,K,a,b;
scanf("%d",&T);
while(T--)
{
scanf("%d%d%d",&K,&a,&b);
printf("Case %d: %lld\n",++kase,work(K,a,b) );
}
return 0;
}
当初没有仔细分析变化过程,我还认为递归会导致超时,最后又实在是没有其他办法能解决,看了下书上例题后的备注,写着递归两字。
因为k最大是30,也就是说递归最大层数为31,但是要求每一个递归函数里面必须只能调用1个参数不同的自己,比如f(x,y)里面可以调用k*f(a,b),但是不能同时调用p*f(a,b)和q*f(c,d) ( <a,b>!=<c,d>)。
因为这样会导致超时 : 递归到最底层时,计算次数2^30。