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;
    }
  • 相关阅读:
    JID 2.0 RC4 发布,高性能的 Java 序列化库
    FBReaderJ 1.6.3 发布,Android 电子书阅读器
    Arquillian 1.0.3.Final 发布,单元测试框架
    JavaScript 的宏扩展 Sweet.js
    Hypertable 0.9.6.5 发布,分布式数据库
    JRuby 1.7.0 发布,默认使用 Ruby 1.9 模式
    httppp 1.4.0 发布,HTTP响应时间监控
    Redis 2.6.0 正式版发布,高性能K/V服务器
    OfficeFloor 2.5.0 发布,IoC 框架
    XWiki 4.3 首个里程碑发布
  • 原文地址:https://www.cnblogs.com/wxjor/p/7528844.html
Copyright © 2011-2022 走看看