【Chapter08】UVA 10706
链接:戳我
用了快一个小时才弄出来呢。还是不够熟练。
我的解法是这样的:
1. 首先建造两个array
第一个num[]:用来存1~n这串数字的digit的数量
第二个total[]:用来存1121231234....n这串数字的digit的数量
方法:
1) num[i] = num[i-1] + digits_of_number(i)
2) total[i] = total[i-1] + num[i]
2. 然后在获得一个target之后:
用Binary Search在total[]这个array里面找到一个index k,使得:
total[k-1] < target <= total[k]
于是我们就知道了query属于哪一个1~k的数字串了。接着,再用Binary Search在num[]里面寻找到另一个index: q,使得:
num[q-1] < target-total[k-1] <= num[q]
于是我们就知道了我们要找的这个位置是属于哪个数字的digit了。比如说:k = 11, target-total[k-1] = 11:
1 2 3 4 5 6 7 8 9 1 0 1 1,从上面的算法我们得到q = 10
所以我们确定下来,是数字“10”的某个digit。
3. 得到上面的信息之后,用query-total[k-1]-num[q-1],我们就能得到query指向的index是q这个数字的第(i+1)th index。有i+1是因为,这样的运算是把ditgit的排列看成从1th开始的。
1 import math 2 3 # num[n] = the number of digits in 1~n 4 # s[n] = the number of digits from 1~n: 112123123412345.....digits(n) 5 def digit_sum(n): 6 num = [0] 7 for i in range(1,n): 8 num.append(num[i-1] + len(str(i))) 9 10 s = [0] 11 for i in range(1, n): 12 s.append(s[i-1] + num[i]) 13 14 return num, s 15 16 17 def binary_search(target, array, lower, upper): 18 hit = -1 19 while lower < upper: 20 mid = lower + (upper-lower)/2 21 22 if array[mid] == target: 23 hit = mid 24 break 25 elif array[mid] < target: 26 hit = mid + 1 27 lower = mid + 1 28 else: 29 hit = mid 30 upper = mid 31 32 return hit 33 34 def main(): 35 n = 31463 36 num, total = digit_sum(n) 37 38 with open('10706.txt', 'r') as ins: 39 count = int(ins.readline().strip()) 40 41 for i in range(count): 42 target = int(ins.readline().strip()) 43 index_in_total = binary_search(target, total, 0, n) 44 rest = target - total[index_in_total-1] 45 index_in_num = binary_search(rest, num, 0, n) 46 index = rest - num[index_in_num-1] 47 48 print str(index_in_num)[index-1] 49 50 if __name__ == "__main__": 51 main()
这里的东西都是自娱自乐的.我只是抱着构思算法的心态去做UVA的题.
我所有的code都不可能AC的.因为我就没想着让它能AC.