zoukankan      html  css  js  c++  java
  • 【数形结合】Erratic Expansion

    [UVa12627]Erratic Expansion

    算法入门经典第8章8-12(P245)

     

    题目大意:起初有一个红球,每一次红球会分成三红一蓝,蓝球会分成四蓝(如图顺序),问K时的时候A~B行中有几个红色。

    试题分析:很容易注意到,按照此种规律,矩形的左上角、右上角、左下角总是与上一个时刻的图形一样,这是我们分治的基础。

         那么,既然得到了上面的,利用前缀和的思想,设f(k,i)表示k时刻从1到i行的红色数量,则答案为f(k,B)-f(k,A-1)

         我们知道,第i个时刻的正方形边长为2^k,那么当i小于等于2^k时,就是上一个同样行的红色的数量*2(因为拓展了)

         那么如果i大于2^k时,我们要怎么办呢?

         首先,最显而易见的是左上角与右上角都是上一个时刻的图形,那么k时刻的红色总和为3^k,所以左上角右上角加起来就是2*(3^(k-1))。

         那么剩下的那些也就是同上面的一样计算,也就是f(k-1,i-2^(k-1))了。

     

    代码:

    #include<iostream>
    #include<cstring>
    #include<vector>
    #include<queue>
    #include<algorithm>
    using namespace std;
    
    #define LL long long
    
    inline LL read(){
    	LL x=0,f=1;char c=getchar();
    	for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
    	for(;isdigit(c);c=getchar()) x=x*10+c-'0';
    	return x*f;
    }
    const LL INF=9999999;
    const LL MAXN=100000;
    LL T; LL C[MAXN+1];
    LL Case;
    LL K,N,M; 
    LL F(LL k,LL p){
    	if(p==0) return 0;
    	if(k==0) return 1;
    	if(p>=(1<<(k-1))) return F(k-1,p-(1<<(k-1)))+2*C[k-1];
    	else return 2*F(k-1,p);
    }
    
    int main(){
    	T=read();C[0]=1;
    	for(LL i=1;i<=31;i++) C[i]=C[i-1]*3;
    	while(T--){
    		++Case;
    		K=read(),N=read(),M=read();
    		printf("Case %d: %lld
    ",Case,F(K,M)-F(K,N-1));
    	}
    	return 0;
    }
  • 相关阅读:
    二叉树的层序遍历-102
    剑指offer 06 从尾到头打印链表
    替换空格:剑指offer05
    面试题16.11.跳水板----leetcode
    JVM——垃圾回收
    新生代Eden与两个Survivor区的解释
    JVM 1.8 永久代---元空间 的变动
    Git拉取项目避坑
    python-装饰器
    python-Queue
  • 原文地址:https://www.cnblogs.com/wxjor/p/7528844.html
Copyright © 2011-2022 走看看