Hello r主人。
我需要计算Farey树分数的分母,最高可达2 ** 30。
我使用this approach:
提出了这个C ++解决方案struct FareySB {
int num, den;
FareySB() : den(0) {}
int sum() {
return num + den;
}
};
const int LGMAX = 30;
const int MAX = 1 << LGMAX;
FareySB FTF[MAX];
void get_FTF() {
FTF[0].num = 0; FTF[0].den = 1;
FTF[1].num = 1; FTF[1].den = 1;
FTF[2].num = 1; FTF[2].den = 2;
int k = 3;
for (int i = 1; i < LGMAX; i++) {
int len = 1 << i;
int hlen = len >> 1;
for (int j=0; j<hlen; j++) {
FTF[k].num = FTF[k-hlen].num;
FTF[k].den = FTF[k-hlen].sum();
k++;
}
for (int j=0; j<hlen; j++) {
FTF[k].num = FTF[k-len].den;
FTF[k].den = FTF[k-1-(j<<1)].den;
k++;
}
}
}
要知道第n个词我需要知道所有[0..n-1]项。好到目前为止。
这有一个问题:在大约2 ** 27之后内存就会爆炸。
Farey Tree Fractions的分母是OEIS-A007306:
1,1,3,3,4,4,5,5,4,5,7,8,7,7,8,7 ......
在那个OEIS页面中,我发现了一个代码,它似乎在恒定时间内返回序列的第n个项。如果这是真的,它将解决我的内存限制超出问题。
但是代码是用R语言编写的:
(R)
# Given n, compute directly a(n)
# by taking into account the binary representation of n-1
aa <- function(n){
b <- as.numeric(intToBits(n))
l <- sum(b)
m <- which(b == 1)-1
d <- 1
if(l > 1) for(j in 1:(l-1)) d[j] <- m[j+1]-m[j]+1
f <- c(1, m[1]+2) # In A002487: f <- c(0, 1)
if(l > 1) for(j in 3:(l+1)) f[j] <- d[j-2]*f[j-1]-f[j-2]
return(f[l+1])
}
# a(0) = 1, a(1) = 1, a(n) = aa(n-1) n > 1
对你来说可能很简单,但我不懂R语言,也无法理解上面的代码。
它真的是一个恒定的功能吗?该功能如何运作?
如果你能告诉我这个函数里面发生的n
什么,那么我就可以用C ++编写代码了。
提前致谢。
答案 0 :(得分:1)
我不确定它是如何工作的,但这是R代码正在做的事情。假设n=100
。
b <- as.numeric(intToBits(n))
这会生成n
的(反向)二进制表示的32元素向量。对于n=100
,b
为0 0 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
l <- sum(b)
是b
元素的总和(即1的数量)。在这种情况下l=3
m <- which(b == 1)-1
是b
元素索引的向量,它们等于1,每个都减少1.因此对于n=100
,m= 2 5 6
d <- 1
只需设置d
等于1
if(l > 1) for(j in 1:(l-1)) d[j] <- m[j+1]-m[j]+1
。如果l
大于1,那么d
将成为长度为l-1
的向量,其中每个d
是m
的连续值之间的差异,加一。因此对于n=100
,d= 4 2
f <- c(1, m[1]+2)
将f
设置为第一个值为1
的向量,第二个值为m
的第一个元素,加上2.此处f
为{ {1}}
1 4
。如果if(l > 1) for(j in 3:(l+1)) f[j] <- d[j-2]*f[j-1]-f[j-2]
大于1,则会根据该公式将元素添加到l
的末尾 - 例如f
为f[3]
或d[1]*f[2]-f[1]
。对于4*4-1=15
,n=100
为f
。
1 4 15 26
这将返回return(f[l+1])
的最后一个元素作为结果。
我不确定它是否是常数,但随着f
的增加它看起来很快。祝你好运!