题目描述:现在我们手里有一张2维的正整数(包括0)表. 对于第 i 行第 j 列的那个数我们有如下定义:
a[i][j]是 a[i][k]{其中0<=k<j}和a[k][j]{其中0<=k<i}没有出现的那个最小的正整数
比如a[0][0]=0
;
输出a[x][y]
示例:
输入:x = 0 y = 0
输出:0
分析: 这个题给我一开始,我是想如何去求出一个数学公式去进行一个推导。我连最基础的暴力解法都没有想出来。后来,我直接采用更加暴力的方式,进行了一个模拟。手动模拟
给出我的一组结果。
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
---|---|---|---|---|---|---|---|
1 | 0 | 3 | 2 | 5 | 4 | 7 | 6 |
2 | 3 | 0 | 1 | 6 | 7 | 4 | 5 |
3 | 2 | 1 | 0 | 7 | 6 | 5 | 4 |
4 | 5 | 6 | 7 | 0 | 1 | 2 | 3 |
5 | 4 | 7 | 6 | 1 | 0 | 3 | 2 |
6 | 7 | 4 | 5 | 2 | 3 | 0 | 1 |
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
现在把上面 分成 4 个区域,分别为
1
2
A B
D C
我们观察一下, 可以发现:
- C 区 可以由 A区 翻转得到;
- D 区可以由 B 区翻转得到;
- B 区可以由 A 区 平移加4后得到; (这里的平移加多少是和区的大小有关的)
这就有意思了,将 B C D 转换为 A。 然后一直的转换,直到最后可以直接求和。
现在就出现了一个问题,如何确定,当前元素所在的区呢?
给出一个小小的提示,2的次方,每个小区的大小是一样的,大区的大小和2的次方有关。
代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
ans = 0
ans_lst = [
[0, 1, 2, 3],
[1, 0, 3, 2],
[2, 3, 0, 1],
[3, 2, 1, 0]
]
"""
A B
D C
"""
while True:
if x < 4 and y < 4:
print(ans + ans_lst[x][y])
break
temp = 1
max_x = max(x, y)
while temp <= max_x:
temp *= 2
if x >= temp//2 and y >= temp//2:
# 在 C 区
x = temp - 1 - x
y = temp - 1 - y
elif x >= temp//2 and y < temp//2:
# 在 D 区
x, y = y, x
ans += temp//2
y -= temp//2
elif x < temp//2 and y >= temp//2:
# 在 B 区
ans += temp//2
y -= temp//2
else:
# 在A区, 不可能在A区
pass