在恒定时间内找到Farey树分数的分母

时间:2018-01-12 17:24:34

标签: r

Hello 主人。

我需要计算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 ++编写代码了。

提前致谢。

1 个答案:

答案 0 :(得分:1)

我不确定它是如何工作的,但这是R代码正在做的事情。假设n=100

b <- as.numeric(intToBits(n))这会生成n的(反向)二进制表示的32元素向量。对于n=100b0 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)-1b元素索引的向量,它们等于1,每个都减少1.因此对于n=100m= 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的向量,其中每个dm的连续值之间的差异,加一。因此对于n=100d= 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的末尾 - 例如ff[3]d[1]*f[2]-f[1]。对于4*4-1=15n=100f

1 4 15 26这将返回return(f[l+1])的最后一个元素作为结果。

我不确定它是否是常数,但随着f的增加它看起来很快。祝你好运!