约瑟夫环

来源:互联网 发布:大数据分析导论 感想 编辑:程序博客网 时间:2024/06/11 09:27
输入n、m,总人数为n,每数到m杀一个人(这里设第一个序号为 t)
例:n=6, m=2
    1, 2, 3, 4, 5, 6
    1,   , 3, 4, 5, 6
    1,   , 3,   , 5, 6
    1,   , 3,   , 5, 
    1,   ,   ,   , 5, 
      ,   ,   ,   , 5, 
设 f(n) 为第n个人死时,最后一个人的人序号,当时有 1个人
设 f( i) 为第 i个人死时,最后一个人的人序号,当时有 n-i+1个人
现有,
    f(n) = 1
    f(n-1) = [f(n)+m]%2
    f( i) = [f(i+1) +m]%(n-i+1)
于是,从 f(n)一直推算出 f(1),需要执行 +m)%(n-i+1) 共 n-1 次

实现:
    int t = 1;
    for( int i = 2; i <= n; ++i)
    {
        t = (t+m)%i;
    }
    cout << t << endl;

注意,这里有一个错误,在 n-1次循环中,我们使用了求余运算,假设除数为i,则取值范围为[0, i-1]
而我们一直的计数是从1到n,而不是 0到n-1,如这还有3个人,我们的计数是 1,2,3,而不是 0,1,2
这就导致了当 t + m == i 时,我们原先的计数方式就使得 t = 0 而不可能取到 t = i,若单独拿出来判断浪费资源
加入判断,
    t = (t+m)%i;
    if( t == 0)
        t = i;
故而,这里我们取从t=0开始计数的计数方式,计算过程不需要判断其它情况,若想得到原来计数方式的结果,+1即可

原创粉丝点击