无限递归字符串查询
题目描述
Description
Consider a string A = “12345”. An infinite string s is built by performing infinite steps on A recursively. In i-th step, A is concatenated with ‘$’ i times followed by reverse of A. A=A|$…$|reverse(A), where | denotes concatenation.
Constraints:1<=Q<=10^5, 1<=POS<=10^12
Input
输入第一行为查询次数,后面为每次查询的具体字符位置。
Output
输出每一次查询位置上的字符。
Sample Input 1
2
3
10
Sample Output 1
3
2
题目解析:
题目中的A=A|$...$|reverse(A)是什么意思呢,如下所示
A1 = 12345
A2 = 12345$54321 = A1|$*1|reverse(A1)
A3 = 12345$54321$$12345$54321 = A2|$*2|reverse(A2) = A2|$*2|A2
...
An = An-1|$*n-1|reverse(An-1) = An-1|$*n-1|An-1
思路解析:
- 除A1外,所有字符串都是对称的,即A = reverse(A),所以初始状态从A2也就是12345$54321 开始,所有的字符串都满足规律An = An-1|$*n-1|An-1
- 根据查询的位置q构造字符串Ai ,直到len(Ai-1 )< q <=len(Ai)为止,此时第Ai个字符串的长度一定大于查询的位置q,第Ai-1个字符串的长度一定小于q,意味着这个字符串是刚刚够查询的.并保存此时的$符的数量与字符串长度
- 查询位置q(len(Ai-1 )< q <=len(Ai))一定满足如下几种情况
- 若 len(Ai-1 )<q<=len(Ai-1 )+len($),说明q所在的位置是$
- 若 len(Ai-1 )+len($)<q,观察An的结构(An = An-1|$*n-1|An-1),说明q所在的位置是在An-1中,此时去An-1中寻找,将查询位置q更新为q = q-len(Ai-1 )+len($),
- 重复以上过程,直到q<len(A2)为止(此时可以直接用A2[q-1]来获得字符)
代码
# q 所求的第q个位置
# 返回 第q个位置所在的字符串
def GetValues(q):
size = 5 # 计算字符串的数量 初始为5
itr = 0
while True:
if q <= size:
return size, itr # 返回值 字符串长度, $符号的数量
itr += 1 # 计算$符的数量 ,每次$符号的数量+1
size = (size * 2) + itr # 第一次为11 12345$54321 每次新字符串的长度等于两倍的原来字符串的长度加上$符号的个数
def GetChar(q):
g_str = ['1', '2', '3', '4', '5', '$', '5', '4', '3', '2', '1']
while q > len(g_str):
# 构造出一个位置上包含q的串, 如果 A<=q 则停止构造
m, itr = GetValues(q) # q 一定大于等于A的长度 (m - itr) / 2)
# 因为字符串的形式是A|$*n|reverse(A)
# 这里我们首先求出A|$*n|的长度 , 用总长度-$_长度再除以2再加上|$*n|
val = int(((m - itr) / 2) + itr) # 若 A=<q<=A+n 则是$符号
if q <= val: # 若所求长度比A长度小
q = 6
break
q -= val # 若所求长度比A长度大,则所求的字符位置在reverse(A)中 #若 A+n<q 说明在上一个A串中
if q > 0:
return g_str[q - 1]
return ""
if __name__ == '__main__':
case_num = [int(x) for x in input().strip().split(" ")][0]
for i in range(case_num):
x = int(input().strip())
print(GetChar(x ))
来源:CSDN
作者:年糕糕糕
链接:https://blog.csdn.net/qq_33935895/article/details/102937950