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. IDEA/WebStorm使用笔记

    1.使用powershell作为默认终端 #改变powershell策略 Set-ExecutionPolicy Unrestricted -Scope CurrentUser 找到系统的powers ...

  2. PHP Math函数

    abs() 绝对值.   acos() 反余弦.   acosh() 反双曲余弦.   asin() 反正弦.   asinh() 反双曲正弦.   atan() 反正切.   atan2() 两个参 ...

  3. java 线程同步、死锁

    转载地址:速学堂 https://www.sxt.cn/Java_jQuery_in_action/eleven-thread-synchronization.html 什么是线程同步  同步问题的提 ...

  4. ESlint 格式化代码 备忘

    vscode 代码格式化配置 vscode 菜单 文件->首选项->设置 --->进入扩展查找到ESlint,点击任一选项中的[在setting.json中配置],复制以下代码 { ...

  5. mysql database和schema区别

    在MySQL的语法操作中(MySQL5.0.2之后),可以使用CREATE DATABASE和CREATE SCHEMA来创建数据库,两者在功能上是一致的.在使用MySQL官方的MySQL管理工具My ...

  6. POJ1979(Red and Black)--FloodFill

    题目在这里 题目意思是这样的,一个人起始位置在    '@'  处,他在途中能到达的地方为 ' .  '     而  '#' 是障碍物,他不能到达. 问途中他所有能到达的   '.'的数量是多少 ? ...

  7. http://go.microsoft.com/fwlink/?linkid问题

    今天不知怎的,打开一个网页出现了http://go.microsoft.com/fwlink/?linkid=XXX 烦死了,在百度搜了下方法,什么改注册表,策略模板等不见起效.其实打开IE的设置, ...

  8. BeautifulSoup库的安装与使用

    BeautifulSoup库的安装 Win平台:“以管理员身份运行” cmd 执行 pip install beautifulsoup4 演示HTML页面地址:http://python123.io/ ...

  9. awk 条件及循环语句和字符串函数

    条件语句 if(条件表达式) 动作1 else if(条件表达式) 动作2 else 动作3 循环语句: while循环: while(条件表达式) 动作 do while循环: do 动作 whil ...

  10. 五、DML操作汇总

    前言: DML(Data Manipulation Language)数据操作语言,以INSERT.UPDATE.DELETE三种指令为核心,分别代表插入.更新与删除,是必须要掌握的指令,DML和SQ ...