博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
2016"百度之星" - 初赛(Astar Round2A)1005 BD String(HDU5694)——找规律、字符串对称、分治...
阅读量:6293 次
发布时间:2019-06-22

本文共 1558 字,大约阅读时间需要 5 分钟。

  分析:按照题目所给的意思每次处理得到的新的字符串都是具有高度对称性的,举个例子,如题目所给的第三个字符串,最中间的是B然后两边分散开去,一边是B的话另外一边关于这个中心对称的那个位置一定是D,反过来同理。那么从任意一点,只要找出他的对称中心,从对称中心的另一边到这一点他们之间的所有字符中,去除掉对称中心是B以外,其他的那些字母中,B和D的个数一定是相等的(从题目中所给的变换方法可知)。那么这题就很简单了。就是关于这个对称中心找出这点到其对称点的长度len,B的个数就是len/2+1,因为len显然是奇数,所以(len+1)/2也无妨。

  我们定义dfs(x)表示从第一个到第x个有多少个B,于是从l到r的答案就是dfs(r)-dfs(l-1)。那么现在不妨拿这个长度为7的BBDBBDD来说明dfs这个方法,如果x是7,它是处于这个对称区间的边缘的,直接给出(7+1)/2=4就好了,但是如果是6呢?很显然的要求1到6的B的个数的话,关于第四个对称,字符串被分割成了B BDBBD D这样子,单单用(5+1)/2只能得到3,原因很简单,第一个字母没被考虑,那么只要在对剩下的部分递归进行同样的操作即可。

  关于是不是这个位置处于边界,我们可以简单地预处理出每个字符串的长度:1,3,7,15... ...这样子的话就可以很容易的知道x是属于哪个对称区间里面了,具体见代码:

1 #include 
2 #include
3 #include
4 #include
5 using namespace std; 6 typedef long long ll; 7 8 vector
V; 9 void init()10 {11 ll x=1;12 while(x<=(ll)1e18)13 {14 V.push_back(x);15 x=2*x+1;16 }17 }18 19 ll dfs(ll x)20 {21 if(x==0) return 0;22 int y=lower_bound(V.begin(),V.end(),x)-V.begin();//找出x被包含在那个对称区间里面23 if(V[y]==x) return (x+1)/2; //如果刚好处于对称区间的边缘,直接返回,因为前面没有没被处理完的字母了24 ll t = V[y-1]+1; //不然的话,很显然前面那个字符串的最后一个位置加1就是x处于的对称区间的对称中心25 return x-t+1+dfs(x-2*(x-t)-1); //分治剩余部分26 }27 28 int main()29 {30 init();31 int T;32 scanf("%d",&T);33 while(T--)34 {35 ll l,r;36 scanf("%I64d%I64d",&l,&r);37 ll ans = dfs(r)-dfs(l-1);38 printf("%I64d\n",ans);39 }40 return 0;41 }

 

转载于:https://www.cnblogs.com/zzyDS/p/5516600.html

你可能感兴趣的文章
Linux 性能诊断 perf使用指南
查看>>
实操分享:看看小白我如何第一次搭建阿里云windows服务器(Tomcat+Mysql)
查看>>
Sphinx 配置文件说明
查看>>
数据结构实践——顺序表应用
查看>>
python2.7 之centos7 安装 pip, Scrapy
查看>>
机智云开源框架初始化顺序
查看>>
Spark修炼之道(进阶篇)——Spark入门到精通:第五节 Spark编程模型(二)
查看>>
一线架构师实践指南:云时代下双活零切换的七大关键点
查看>>
ART世界探险(19) - 优化编译器的编译流程
查看>>
玩转Edas应用部署
查看>>
music-音符与常用记号
查看>>
sql操作命令
查看>>
zip 数据压缩
查看>>
Python爬虫学习系列教程
查看>>
【数据库优化专题】MySQL视图优化(二)
查看>>
【转载】每个程序员都应该学习使用Python或Ruby
查看>>
PHP高级编程之守护进程,实现优雅重启
查看>>
PHP字符编码转换类3
查看>>
rsync同步服务配置手记
查看>>
http缓存知识
查看>>