题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4352
--------------------------------------------------------------------------------------------------------------------------------------------------------------------
题意:气球按照一定方式进行复制,要求给出数量。
思路:
根据题目提示,这道题可以用f(k,i)表示k小时后最上边i行的红气球总数那么我们的答案就可以表示为f(k,b)-f(k,a-1)这里我们通过观察,在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。同理,我们也可以利用g(k,i)表示k小时后最下边i行的红气球总数,将答案用g(k,i)表示出来。
代码:
#include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<string> #include<vector> #include<stack> #include<bitset> #include<cstdlib> #include<cmath> #include<set> #include<list> #include<deque> #include<map> #include<queue> using namespace std; typedef long long ll; const double PI = acos(-1.0); const double eps = 1e-6; ll c[30]={1}; ll ballon(ll K,ll i){ if(i<=0) return 0; if(K==0) return 1; if(i<=pow(2,K-1)) return 2*ballon(K-1,i); else return 2*c[K-1]+ballon(K-1,i-pow(2,K-1)); } int main(void){ for(int p=1;p<=30;p++){ c[p]=c[p-1]*3; } int T=0; scanf("%d",&T); int count =1; //freopen("out.txt","wa",stdout); for(int i=0;i<T;i++){ ll K,A,B; scanf("%lld %lld %lld",&K,&A,&B); printf("Case %d: %lld\n",count,ballon(K,B)-ballon(K,A-1)); count++; } return 0; }