我有两个查询表,如果可能的话,我想用简单的数学来消除。
第一个是从数组中的索引到序列{0} =>的映射。 1,{1,2} => 2,{3,4,5} => 3,s.t。有一个,两个2s,三个3s等。或者视觉上:
lookup1[N] = {
1,
2, 2,
3, 3, 3,
4, 4, 4, 4,
5, 5, 5, 5, 5,
6, 6, 6, 6, 6, 6,
7, 7, 7, 7, 7, 7, 7,
8, 8, 8, 8, 8, 8, 8, 8,
...
}
第二个是增加序列,第一个序列是(1),第二个(1,2),第三个(1,2,3)。它类似于模数周期,但在每个周期后增加。目测:
lookup2[N] = {
1,
1, 2,
1, 2, 3,
1, 2, 3, 4,
1, 2, 3, 4, 5,
1, 2, 3, 4, 5, 6,
1, 2, 3, 4, 5, 6, 7,
1, 2, 3, 4, 5, 6, 7, 8,
1, 2, 3, 4, 5, 6, 7, 8, 9,
...
}
这些需要从索引进行映射。对于第二次查找,输入5,4,3将分别映射到3,2,1。
是否有任何数学公式可以产生这些模式?我宁愿执行一些指令而不是内存访问。
答案 0 :(得分:3)
对于lookup1,这看起来与Triangular numbers密切相关,实际上它是反问题。三角形数字是具有n行的三角形中的项目数。所以你有T1 = 1,T2 = 1 + 2 = 3,T3 = 1 + 2 + 3 = 6,T4 = 1 + 2 + 3 + 4 = 10.或者作为函数f(1)= 1,f( 2)= 3,f(3)= 6,f(4)= 10.
你想做倒数,所以g(1)= 1,g(3)= 2,g(6)= 3,g(10)= 4.我们稍后会担心其他值。
有一个三角数f(n)= n(n + 1)/ 2的公式。一个更复杂的公式用于逆
g(n) = (sqrt(8 * n + 1) - 1) / 2
一个小实验表明
ceil((sqrt(8*n+1) - 1) / 2 )
给出你想要的数字。
对于第二部分,您可以使用反三角数函数,然后找到前一个三角数,并取差值
X = ceil((sqrt(8*n+1) - 1) / 2);
T = (X * (X-1))/2 ;
print(n-T);
轻微的警示。在转换点sqrt(8*n+1)
应评估为奇整数值。对于非常大的n可能会发生的事情比舍入错误可能会产生影响。我已经测试了这个超过一百万,并且没有看到问题发生。