zoukankan      html  css  js  c++  java
  • 二分算法题目训练(一)——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,它自己会产生多少炮弹。
    • 设计思路
      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[1] = 1;
        for(i=2; i<Maxn; i++)
        {
            a[i] = a[i-1]+i;
        }
        sum[1] = 1;
        for(i=2; i<Maxn; i++)
        {
            sum[i] = sum[i-1]+a[i];
        }
        int t;
        scanf("%d",&t);
        while(t--)
        {
            LL num;
            cin >> num;
            LL p = find_index(sum,Maxn,num);
            num -= sum[p-1];
            LL row = find_index(a,Maxn,num);
            LL col = num-a[row-1];
            cout<<p<<" "<<row<<" "<<col<<endl;
        }
        return 0;
    }
    LL find_index(LL *array,LL size,LL key)
    {
        int first = 0, last = size-1;
        int middle, pos=0;
    
        while(first < last)
        {
            middle = (first+last)/2;
            if(array[middle] < key)
            {
                first = middle + 1;
                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[1] = 1;
        for(i=2;i<Maxn;i++)
        {
            a[i] = a[i-1]+i;
        }
        sum[1] = 1;
        for(i=2;i<Maxn;i++)
        {
            sum[i] = sum[i-1]+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-1];
            LL row = lower_bound(a,a+Maxn,num)-a;
            LL col = num-a[row-1];
            cout<<p<<" "<<row<<" "<<col<<endl;
        }
        return 0;
    }
  • 相关阅读:
    SharePoint 2013 中的SQL Server 安全
    SharePoint 2013 的HTML5特性之响应式布局
    SharePoint 2013 一些小技巧
    SharePoint 2013 排错之"Code blocks are not allowed in this file"
    SharePoint 2013 创建搜索中心及搜索设置
    SharePoint 2013 使用PowerShell创建State Service
    SharePoint 2013 内容部署功能简介
    SharePoint 使用PowerShell恢复误删的网站集
    SharePoint 自定义WebPart之间的连接
    linux之misc及使用misc创建字符设备
  • 原文地址:https://www.cnblogs.com/NikkiNikita/p/9450725.html
Copyright © 2011-2022 走看看