二分算法题目训练(一)——Shell Pyramid详解
HDU2446——Shell Pyramid 详解
- Shell Pyramid
题目描述(Google 翻译的)
在17世纪,由于雷鸣般的喧嚣,浓烟和炽热的火焰,海上的战斗与现代战争一样。但那时,大炮非常简单。它就像一个铁缸,其后端密封,前端打开。它的后端有一个小孔,用来安装保险丝。战舰上的大炮被放在有四个轮子的小型车辆上,炮弹是铁球,里面装着火药。当时,据说有一位聪明的船长,他也是一位数学家的业余爱好者。他喜欢把他遇到的所有东西都连接到数学上。在每次战斗之前,他经常命令士兵将炮弹放在甲板上并使这些炮弹形成炮弹金字塔。
现在让我们假设一个壳金字塔有四层,每层都会有一系列序数。它们如下图所示:
在该图中,它们分别是从左到右的第一层,第二层,第三层和第四层。
在第一层中,只有1个壳,其序数为1.在第二层中,有3个壳,它们的序数为1,2和3.在第三层中,有6个壳,它们的序数分别为1,2,3,4,5和6.在第四层中,有10个壳,它们的序数在上图中显示。
整个贝壳金字塔也有序列号。例如,第二层中第三个外壳的序列号为4,第三层中第五个外壳的序列号为9,第四层中第九个外壳的序列号为19。
还有一个相互关联的问题:如果给出一个序列号s,那么我们可以计算出第s个shell是在什么层,什么行和什么列。假设层数是i,行数是j而列数是k,因此,如果s = 19,则i = 4,j = 4并且k = 3。
现在让我们继续讲述船长的故事。
一场战斗即将开始。船长给每个大炮分配了相同数量的炮弹。炮弹堆放在甲板上,由炮弹形成相同的炮弹金字塔。当敌人的战舰靠近时,船长命令同时开火。然后听到了雷鸣般的声音。船长仔细听了,然后他就知道有多少炮弹被使用了,剩下多少炮弹了。在战斗结束时,船长赢了。在休息期间,他向下属询问了一个问题:对于壳金字塔,如果给出序列号s,你如何计算层数i,行号j和列号k?
- 输入
首先输入一个数字n,再进行n个案例。对于每种情况,都有一个足够大的壳金字塔,给出一个整数,这个整数是序列号s(s <2 ^ 63)。有几个测试用例。输入由文件末尾终止。 - 输出
对于每种情况,输出相应的层编号i,行编号j和列编号k。 - 样例输入
2
19
75822050528572544 - 样例输出
4 4 3
769099 111570 11179 - 思路分析
- 首先通过二分先确定给出的数字是哪个金字塔,要找到是哪个金字塔,就需要知道给定序号代表的意思,序号是宏观的炮弹下标,因此它必然代表之前已经出现的所有炮弹,要找到它属于第几个金字塔,就需要一个数组来存储对于金字塔序号 i,它和它之前所有的金字塔会产生多少炮弹。
- 再通过二分确定是属于这个金字塔的哪一层。要找到它是哪一层,就需要知道这个金字塔有多少个炮弹,因此还需要一个数组来存储对于金字塔序号 i,它自己会产生多少炮弹。
- 设计思路
- 对于第 i 个金字塔,它所包含的炮弹数都是第 i-1 个金字塔所包含的炮弹数加上 i,比如第二个金字塔有 3 个炮弹,那么第三个就有 3+3 个炮弹,因此得到非递减序列 a[i] = a[i-1] + i
- 对于第 i 个金字塔,所有的炮弹数目为 i-1 个金字塔所包含炮弹数目与自己含有炮弹之和,因此得到非递减序列 sum[i] = sum[i-1] + a[i]
- 接下来只需要两次二分找出结果,找到金字塔序号 p 后,减去sum[p-1],就会得到所在金字塔中第多少个炮弹,找到行号 row 后,减去a[row-1],就是列号。
#include <iostream>
#include <cstdio>
#include<cmath> #define Maxn 1000000 using namespace std; typedef long long int LL; LL a[Maxn];
LL sum[Maxn]; LL find_index(LL *array,LL size,LL key); int main()
{
int i;
a[] = ;
for(i=; i<Maxn; i++)
{
a[i] = a[i-]+i;
}
sum[] = ;
for(i=; i<Maxn; i++)
{
sum[i] = sum[i-]+a[i];
}
int t;
scanf("%d",&t);
while(t--)
{
LL num;
cin >> num;
LL p = find_index(sum,Maxn,num);
num -= sum[p-];
LL row = find_index(a,Maxn,num);
LL col = num-a[row-];
cout<<p<<" "<<row<<" "<<col<<endl;
}
return ;
}
LL find_index(LL *array,LL size,LL key)
{
int first = , last = size-;
int middle, pos=; while(first < last)
{
middle = (first+last)/;
if(array[middle] < key)
{
first = middle + ;
pos = first;
}
else
{
last = middle;
pos = last;
}
}
return pos;
}
- 对于非递减序列,可以使用 STL 中的 lower_bound()
#include <iostream>
#include <cstdio>
#include<cmath> #define Maxn 1000000 using namespace std; typedef long long int LL; LL a[Maxn];
LL sum[Maxn]; int main()
{
int i;
a[] = ;
for(i=;i<Maxn;i++)
{
a[i] = a[i-]+i;
}
sum[] = ;
for(i=;i<Maxn;i++)
{
sum[i] = sum[i-]+a[i];
}
int t;
scanf("%d",&t);
while(t--)
{
LL num;
cin >> num;
LL p = lower_bound(sum,sum+Maxn,num)-sum;
num -= sum[p-];
LL row = lower_bound(a,a+Maxn,num)-a;
LL col = num-a[row-];
cout<<p<<" "<<row<<" "<<col<<endl;
}
return ;
}
二分算法题目训练(一)——Shell Pyramid详解的更多相关文章
- 二分算法题目训练(四)——Robin Hood详解
codeforces672D——Robin Hood详解 Robin Hood 问题描述(google翻译) 我们都知道罗宾汉令人印象深刻的故事.罗宾汉利用他的射箭技巧和他的智慧从富人那里偷钱,然后把 ...
- 二分算法题目训练(三)——Anton and Making Potions详解
codeforces734C——Anton and Making Potions详解 Anton and Making Potions 题目描述(google翻译) 安东正在玩一个非常有趣的电脑游戏, ...
- 二分算法题目训练(二)——Exams详解
CodeForces732D——Exams 详解 Exam 题目描述(google翻译) Vasiliy的考试期限将持续n天.他必须通过m门科目的考试.受试者编号为1至m. 大约每天我们都知道当天可以 ...
- adb shell 命令详解,android
http://www.miui.com/article-275-1.html http://noobjava.iteye.com/blog/1914348 adb shell 命令详解,android ...
- [转]EM算法(Expectation Maximization Algorithm)详解
https://blog.csdn.net/zhihua_oba/article/details/73776553 EM算法(Expectation Maximization Algorithm)详解 ...
- 【Devops】【docker】【CI/CD】关于jenkins构建成功后一步,执行的shell命令详解+jenkins容器运行宿主机shell命令的实现方法
1.展示这段shell命令 +详解 #================================================================================= ...
- Linux主要shell命令详解(上)
[摘自网络] kill -9 -1即实现用kill命令退出系统 Linux主要shell命令详解 [上篇] shell是用户和Linux操作系统之间的接口.Linux中有多种shell,其中缺省使用的 ...
- adb shell 命令详解,android, adb logcat
http://www.miui.com/article-275-1.html http://noobjava.iteye.com/blog/1914348 adb shell 命令详解,android ...
- linux shell `符号详解
linux shell `符号详解 <pre>[root@iZ23uewresmZ arjianghu]# echo `ls`asss.html common guaji.php imag ...
随机推荐
- SpringBoot学习(五)—— springboot快速整合Druid
Druid连接池 简介 由阿里巴巴开源的druid连接池是目前综合实力最突出的数据库连接池,而且还提供了监控日志功能,能够分析SQL执行情况. 引入druid连接池 pom.xml中加入 <de ...
- WebClient 下载文件
WebClient用法小结(转载) 如果只想从特定的URI请求文件,则使用WebClient,它是最简单的.NET类,它只用一两条命令执行基本操作,.NET FRAMEWORK目前支持以http: ...
- Eclipse下使用Maven创建项目出现的archetype错误,记,转
记自:http://blog.csdn.net/ZhuboSun/article/details/50099635 [1]出现的错误提示: Unable to create project from ...
- 3_PHP表达式_4_PHP运算符
以下为学习孔祥盛主编的<PHP编程基础与实例教程>(第二版)所做的笔记. 3.4.1 算术运算符 <?php $num1 = -10; $num2 = -4; $num3 = $nu ...
- 开源项目hutool之zip_slip漏洞
今天突然看到了去年写的一篇漏洞分析文章,搬到博客上 ---------------- Hutool是Github上的一个开源项目,是一个java的工具包,对文件.流.加密解密.转码.正则.线程.XML ...
- Java并发 行级锁/字段锁/表级锁 乐观锁/悲观锁 共享锁/排他锁 死锁
原文地址:https://my.oschina.net/oosc/blog/1620279 前言 锁是防止在两个事务操作同一个数据源(表或行)时交互破坏数据的一种机制. 数据库采用封锁技术保证并发操作 ...
- springcloud 之Ribbon客户端负载均衡配置使用
pom.xml添加配置说明:这里服务注册与发现用的是Eureka,所以消费者端需要引入eureka,使用EurekaClient来调用服务 <dependency> <groupId ...
- 【DRF框架】序列化组件——ModelSerializer
ModelSerializer 1.ModelSerializer类似于ModelForm 2.根据模型自动生成一组字段 3.自带实现了.update()以及.create()方法 ModelSeri ...
- Django的安装和使用
一.安装 ① 命令行安装 # 命令提示符下 # 方式一 pip install django==1.11.16 -i https://pypi.tuna.tsinghua.edu.cn/simple ...
- vsftpd设置虚拟用户
centos6.5环境 软件安装: yum install vsftpd db4-utils 1. 添加虚拟用户口令文件 #添加一个虚拟用户testvim /etc/vsftpd/vftp_vuser ...