📜  门| Gate IT 2005 |问题28(1)

📅  最后修改于: 2023-12-03 15:42:13.969000             🧑  作者: Mango

门| Gate IT 2005 |问题28

题目描述

有一个无限长的整数序列 1, 2, 2, 3, 3, 3, 4, 4, 4, 4, …,按照其中每个数的出现次数将这个无限长的序列抽象成一个无限深度的序列树。例如,前10个元素对应的树为:

      1
     / \
    2   2
   / \ / \
  3  3 3  3
 / \
4   4

现在给定整数 x 和 y,请你求得对应于序列树上从根节点开始的第 x 个节点,以及第 y 个节点在同一层上且在这个节点的左边的第一个节点。

输入格式

一行中输入两个无空格的正整数 x 和 y(1≤x≤1e5,x≤y≤1e5)。

输出格式

输出两行,第一行为第 x 个节点,第二行为第 y 个节点在同一层上且在这个节点的左边的第一个节点。

样例输入
10 12
样例输出
3
2
解题思路

此题要求在序列树中查询第 x 个节点和第 y 个节点在同一层上且在它之前的第一个节点。

首先需要对这个序列树进行分析,可以发现这个序列树是一个正向斜向右增长的等腰直角三角形,因此可以用数学的方式计算出序列树中第 x 个节点所在的行号以及该行中的第几个节点,并计算出第 y 个节点在它所在的行中的位置。

接下来只需基于行号和节点位置进行计算即可。

参考代码
def find(x):
    """
    找到 x 所在层数以及该层中的位置
    """
    s, cnt = 0, 0 # s 为当前层数的起始数,cnt 为当前已经数了几个数
    while cnt < x:
        s += 1
        cnt += s
    row = s # 第 x 个数所在的行
    pos = x - cnt + row # 第 x 个数在第 row 行中的位置
    return row, pos

x, y = map(int, input().split())
 
row_x, pos_x = find(x)
row_y, pos_y = find(y)
 
ans_x = (row_x - 1) * (row_x - 2) // 2 + pos_x # 第 x 个数在序列中的位置
ans_y = (row_y - 1) * (row_y - 2) // 2 + pos_y # 第 y 个数在序列中的位置
 
if row_x == row_y:
    pos_left = pos_y - 1 # 第 y 个数在该行中左侧的第一个数的位置
else:
    pos_left = 1 # 第 y 个数所在的行不在第 x 个数所在的行的正下方,因此第 y 个数左侧的第一个数为第 1 个数
 
print(ans_x)
print(ans_left)

时间复杂度:$O(\sqrt{n})$,其中 n 为查询的数值范围。