Josephus for large n(Facebook黑客杯)

时间:2011-01-30 20:20:07

标签: algorithm math josephus

上周我参加了Facebook Hacker杯的第1b轮。

其中一个问题基本上是Josephus problem

我之前研究过约瑟夫斯问题是一个离散的数学问题,所以我基本上理解如何重现:

f(n,k) = (f(n-1,k) + k) mod n, with f(1,k) = 0

但是这在Facebook黑客杯中没有用,因为n的最大值是10 ^ 12。 k的mak值为10 ^ 4。

维基百科提到了一种方法,当k很小而n很大时。基本上从一轮中删除人,然后重新编号。 但它描述不多,我不明白为什么重编号会起作用。

我查看了解决方案的示例工作源代码,但我仍然不理解最后一部分。

long long joseph (long long n,long long k) {
    if (n==1LL) return 0LL;
    if (k==1LL) return n-1LL;
    if (k>n) return (joseph(n-1LL,k)+k)%n;
    long long cnt=n/k;
    long long res=joseph(n-cnt,k);
    res-=n%k;
    if (res<0LL) res+=n;
    else res+=res/(k-1LL);
    return res;
}

我真正不理解的部分是从res-=n%k(以及之后的行)开始。你如何得出这是调整结果的方法?

有人能否说明这是如何推导出来的?或者是一个派生它的链接? (我没有找到关于UVA或topcoder论坛的任何信息)

1 个答案:

答案 0 :(得分:4)

是的,我想我破解了它。

让我们看看迭代如何与n = 10,k = 3:

0 1 2 3 4 5 6 7 8 9    n=10,k=3
1 2   3 4   5 6   0    n=7,k=3

观察第二次迭代的元素如何映射到第一次迭代:它们由n%k转换,因为圆圈环绕。这就是我们通过减去10%3来纠正结果的原因。第二行中的数字显示为k-1的组,因此按res/(k-1)进行更正。

另一个案例在迭代中被进一步打击

0 1 2 3 4     n=5,k=3
2 3   0 1     n=4,k=3

现在j(4,3)返回0,由5%3校正的结果为-2。只有当第二行的结果在最后一个组中时才会发生这种情况,在这种情况下,将n添加到结果中将为我们提供原始索引。