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

Algorithm 删除自然数第k遍中剩余的第(k+;1)个元素,algorithm,math,sieve,number-sequence,Algorithm,Math,Sieve,Number Sequence,在自然数系列中,我们必须在第一遍中删除每个第二个元素。然后在剩余的元素中,在第二遍中每第三次移除一个元素。然后在第k道次时,从剩余的元素中移除第(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遍之后(移除每2个元件之后) 第二次通过后(移除第三个元件后) 第三次通过后(移除第四个元件后)

在自然数系列中,我们必须在第一遍中删除每个第二个元素。然后在剩余的元素中,在第二遍中每第三次移除一个元素。然后在第k道次时,从剩余的元素中移除第(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遍之后(移除每2个元件之后)

第二次通过后(移除第三个元件后)

第三次通过后(移除第四个元件后)

所以,在无限过去之后,它将成为

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的倍数
  • 所以第六个幸运数字是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);
}

解释这一点的链接并没有回答您的问题,但这里是一个更直观的算法的推导,该算法用于计算流的任意元素,速度同样快

让我们调用包含所有整数的初始序列s[0],然后s[1]调用第一次传递后的序列,s[2]调用第二次传递后的序列,依此类推

1 3 7 13 15 19 ...
在序列S[0]上,第N个整数(从零开始的索引)是N+1

1 2 3 4 5 6 7 8 9 10 ...
在序列S[1]上,通过从S[0]访问第(2N)个元素来获得第n个整数。注2N=N+(N第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))
但请注意,当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.

这显示了如何从流中获取第6个“27”(5但基于零的索引)。

如果您在我做的时候问这个问题,您可能会受益匪浅。
get_number(int series, int N):
   if (series == 0):
      return N + 1
   else:
      return get_number(series - 1, N + floor(N / series))
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.