【数形结合】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))了。
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | #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\n" ,Case,F(K,M)-F(K,N-1)); } return 0; } |
你——悟到了么?
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 用 C# 插值字符串处理器写一个 sscanf
· Java 中堆内存和栈内存上的数据分布和特点
· 开发中对象命名的一点思考
· .NET Core内存结构体系(Windows环境)底层原理浅谈
· C# 深度学习:对抗生成网络(GAN)训练头像生成模型
· 趁着过年的时候手搓了一个低代码框架
· 本地部署DeepSeek后,没有好看的交互界面怎么行!
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· 用 C# 插值字符串处理器写一个 sscanf
· 乌龟冬眠箱湿度监控系统和AI辅助建议功能的实现