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,它自己会产生多少炮弹。
  • 设计思路
    1. 对于第 i 个金字塔,它所包含的炮弹数都是第 i-1 个金字塔所包含的炮弹数加上 i,比如第二个金字塔有 3 个炮弹,那么第三个就有 3+3 个炮弹,因此得到非递减序列 a[i] = a[i-1] + i
    2. 对于第 i 个金字塔,所有的炮弹数目为 i-1 个金字塔所包含炮弹数目与自己含有炮弹之和,因此得到非递减序列 sum[i] = sum[i-1] + a[i]
    3. 接下来只需要两次二分找出结果,找到金字塔序号 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详解的更多相关文章

  1. 二分算法题目训练(四)——Robin Hood详解

    codeforces672D——Robin Hood详解 Robin Hood 问题描述(google翻译) 我们都知道罗宾汉令人印象深刻的故事.罗宾汉利用他的射箭技巧和他的智慧从富人那里偷钱,然后把 ...

  2. 二分算法题目训练(三)——Anton and Making Potions详解

    codeforces734C——Anton and Making Potions详解 Anton and Making Potions 题目描述(google翻译) 安东正在玩一个非常有趣的电脑游戏, ...

  3. 二分算法题目训练(二)——Exams详解

    CodeForces732D——Exams 详解 Exam 题目描述(google翻译) Vasiliy的考试期限将持续n天.他必须通过m门科目的考试.受试者编号为1至m. 大约每天我们都知道当天可以 ...

  4. adb shell 命令详解,android

    http://www.miui.com/article-275-1.html http://noobjava.iteye.com/blog/1914348 adb shell 命令详解,android ...

  5. [转]EM算法(Expectation Maximization Algorithm)详解

    https://blog.csdn.net/zhihua_oba/article/details/73776553 EM算法(Expectation Maximization Algorithm)详解 ...

  6. 【Devops】【docker】【CI/CD】关于jenkins构建成功后一步,执行的shell命令详解+jenkins容器运行宿主机shell命令的实现方法

    1.展示这段shell命令 +详解 #================================================================================= ...

  7. Linux主要shell命令详解(上)

    [摘自网络] kill -9 -1即实现用kill命令退出系统 Linux主要shell命令详解 [上篇] shell是用户和Linux操作系统之间的接口.Linux中有多种shell,其中缺省使用的 ...

  8. adb shell 命令详解,android, adb logcat

    http://www.miui.com/article-275-1.html http://noobjava.iteye.com/blog/1914348 adb shell 命令详解,android ...

  9. linux shell `符号详解

    linux shell `符号详解 <pre>[root@iZ23uewresmZ arjianghu]# echo `ls`asss.html common guaji.php imag ...

随机推荐

  1. 一行代码实现Vue微信支付,无需引用wexin-sdk库,前后端分离HTML微信支付,无需引用任何库

    前后端分离项目实现微信支付的流程: 1:用户点击支付 2:请求服务端获取支付参数 3:客户端通过JS调起微信支付(微信打开的网页) * 本文主要解决的是第3步,视为前两步已经完成,能正确拿到支付参数, ...

  2. Go part 6 接口,接口排序,接口嵌套组合,接口与类型转换,接口断言

    接口 接口是一种协议,比如一个汽车的协议,就应该有 “行驶”,“按喇叭”,“开远光” 等功能(方法),这就是实现汽车的协议规范,完成了汽车的协议规范,就实现了汽车的接口,然后使用接口 接口的定义:本身 ...

  3. VBA日期时间函数(十三)

    VBScript日期和时间函数帮助开发人员将日期和时间从一种格式转换为另一种格式,或以适合特定条件的格式表示日期或时间值. 日期函数 编号 函数 描述 1 Date 一个函数,它返回当前的系统日期. ...

  4. 关于Vue-ElementUI修改默认样式不成功问题解决

    Element是一个很好用的组件库,但是有时候我们需要修改一些组件的样式以满足我们自己的需求. 我们用浏览器调试找到相应的class,在本地重写这个class时,发现修改不成功. 这是因为在Vue文件 ...

  5. 判断上传文件是否为excel

    1. 可以在input上传组件上添加属性accept,这样上传文件的时候,就只能选择excel文件了. <input type="file" accept="app ...

  6. 理解JVM之java内存模型

    java虚拟机规范中试图定义一种java内存模型(JMM)来屏蔽掉各种硬件和操作系统内存访问差异,以实现让java程序在各种平台都能打到一致的内存访问效果.所以java内存模型的主要目标是定义程序中各 ...

  7. javascript_11-函数面试题

    函数经典面试题 1.---------------------------- // 解析器: // 预解析 全局作用域 // 先找var .function 和参数 // 找到var和function ...

  8. linux-centos7.6设置固定IP网络方法

    两种方法设置固定IP 本文分别用了虚拟机网络模式桥接模式和Net模式,至于两者直接的区别可查看其他文档. 一.安装时设置固定IP地址 1.在系统设置界面,点击“网络和主机名”选项,可以看到默认是未连接 ...

  9. Python函数Day4

    一.内容补充 __iter__() 就是 iter(),iter() 调用的就是__iter__() __next__() 就是 next(),next()调用的就是__next__() __clos ...

  10. 【转】java注解处理器——在编译期修改语法树

    https://blog.csdn.net/a_zhenzhen/article/details/86065063 前言从需求说起由于相关政策,最近公司安全部要求各系统在rpc接口调用的交互过程中把相 ...