删除自然数的第k遍中的每个第(k + 1)个剩余元素

时间:2012-05-11 12:33:18

标签: algorithm math sieve number-sequence

在自然数系列中,我们要删除第一遍中的每个第二个元素。然后在剩余的元素中,删除第二遍中的每个第3个元素。然后在Kth pass中,从剩余的元素中删除每个第(k + 1)个元素。

该系列将如下所示

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, ...

第一次通过后(删除每个第二个元素后),

1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, ...

第二次通过后,(删除每一个第三个元素后),

1, 3, 7, 9, 13, 15, 19, 21, 25, 27, ...

第3次通过后,(删除每个第4个元素后),

1, 3, 13, 15, 19, 25, 27, ...

因此,在无限通过后,它将成为

1, 3, 7, 13, 19, 27, 39, 49, 63, 79, ...

这个系列也被称为Flavius-Josephus筛。

解决方案,找到系列中的第6个元素:

  • 做6 ^ 2 = 36
  • 下降到5的倍数给35
  • 然后下降到4 = 32
  • 的倍数
  • 然后下降到3 = 30
  • 的倍数
  • 然后下降到2 = 28
  • 的倍数
  • 然后下降到1 = 27
  • 的倍数
  • 所以第6个幸运数字是27。

虽然它有效,但我不明白该解决方案的工作原理?

这是一个C程序,

int calc(int n)
{
   if (n == 1) return 1;
   return calc_rec(n*n, n-1);
}

int calc_rec(int nu, int level)
{
   int tmp;
   if (level == 1) return (nu-1);
   tmp = nu % level;
   return calc_rec(nu - (tmp ? tmp : level), level-1);
}

解释此http://oeis.org/A000960

的链接

1 个答案:

答案 0 :(得分:2)

这不能回答你的问题,但这里是一个更直观的算法的推导,用于计算流的任意元素,速度一样快。

让我们调用包含所有整数S [0]的初始系列,然后在第一遍之后调用S [1]系列,在第二遍之后调用S [2]系列,依此类推。

在系列S [0]上,第N个整数(从零开始的索引)是N + 1。

1 2 3 4 5 6 7 8 9 10 ...

在系列S [1]上,通过从S [0]访问第(2N)个元素来获得第N个整数。注2N = N +(N div 1)。 'div'是整数除法,即除去余数的除法。

1 3 5 7 9 11 13 15 17 ...

在系列S [2]上,通过从S [1]访问第N +(N div 2)个元素获得第N个整数。

1 3 7 9 13 15 19 21 ...

在系列S [3]上,通过从S [2]访问第N +(N div 3)个元素获得第N个整数,依此类推。

1 3 7 13 15 19 ...

因此,您将获得以下递归过程:

get_number(int series, int N):
   if (series == 0):
      return N + 1
   else:
      return get_number(series - 1, N + floor(N / series))

但请注意,当系列> N,floor(N / series)相同为零,因此您可以将其称为get_number(N,N)。

例如,

get_number(5, 5) = get_number(4, 6) = get_number(3, 7) =
  get_number(2, 9) = get_number(1, 13) = get_number(0, 26) = 27.

这显示了如何从流中获得'27'作为第6个(5但基于零的索引)。