📜  谜题81 | 100 人围成一圈,玩枪拼图

📅  最后修改于: 2022-05-13 01:57:25.533000             🧑  作者: Mango

谜题81 | 100 人围成一圈,玩枪拼图

100 人按 1 到 100 的顺序围成一圈。1 号有一把剑。他杀死下一个人(即第 2 号)并将剑交给下一个(即第 3 号)。所有的人都这样做,直到只有 1 人幸存下来。哪个数字最后存活?
从 1 到 100 有 100 人。解决方案:第 73个人最终会活下来

解释 1(直观且合乎逻辑):我们可以观察到,如果站在圆圈中的人数是 2 的幂,那么开始游戏的人会活下来。这是因为每一轮杀戮结束后,剩下的人数会减少2人,没有剩余的人,因此下一轮将再次以最初开始游戏的同一个人开始。这将继续下去。

对于圈子里的人数不是2的幂的情况,那么第一轮当活着的人数变成2的幂时,那么拿着枪的人会赢,因为基本上,他开始了游戏中剩下的人是 2 的幂。所以,对于 100,当剩下 64 人时,需要有 36 人死亡,即一个小于给定数字和 2 的幂的数字。第 36 个被杀死的人将是第 72 个人,因此当剩下的人数为 64 时,第 73 个人将拥有枪。

说明2(代码):
在这里,我们可以定义一个包含 100 个元素的数组,其值从 1 到 100。

  • No.1有剑。他杀死下一个人(即第 2 号)并将剑交给下一个(即第 3 号)。
    我们把数组元素当成了一个人。第一个杀死下一个。因此,从 1 开始,我们将删除下一个元素,即 2。
  • 然后第一个人把剑给下一个,即 3。那个人也会杀死下一个人,这样继续。意思是,在数组中,我们需要从 1 开始并删除所有其他(替代)元素直到 100。(所有偶数都将被删除,我们将只在数组中留下奇数)。

第一轮: 1、3、5、7、9、11、13、15、17、19、21、23、25、27、29、31、33、35、37、39、41、43、45、47 , 49, 51, 53, 55, 57, 59, 61, 63, 65, 67, 69, 71, 73, 75, 77, 79, 81, 83, 85, 87, 89, 91, 93, 75 9 , 99
第二回合: 1、5、9、13、17、21、25、29、33、37、41、45、49、53、57、61、65、69、73、77、81、85、89、93 , 97
第三轮: 1, 9, 17, 25, 33, 41, 49, 57, 65, 73, 81, 89, 97
第 4 轮: 9、25、41、57、73、89
第 5 轮: 9、41、73
第 6 轮: 9、73
第 7 轮: 73



为了避免上面的手动计算,这里的通用算法:
步骤 1:对于给定的 N 值,找到立即大于 N 的“2 的幂”。我们称之为 P
步骤 2:从 (P-1) 中减去 N。让我们称它为 M,即 M = (P-1)- N
第 3 步:将 M 乘以 2。即 M*2
步骤 4:从 P-1 中减去 M*2。我们称之为 ans,即 ans = (P-1) – (M*2)
因此,编号为“ans”的人将活到最后。

代码:

C++
#include 
using namespace std;
 
int main()
{
 
    int person = 100;
 
    // Placeholder array for person
    vector a(person);
 
    // Assign placeholders from 1 to N (total person)
    for (int i = 0; i < person; i++) {
        a[i] = i + 1;
    }
 
    // Will start the game from 1st person (Which is at
    // placeholder 0)
    int pos = 0;
 
    // Game will be continued till we end up with only one
    // person left
    while (a.size() > 1) {
        // Current person will shoot the person next to
        // him/her. So incrementing the position.
        pos++;
        // As person are standing in circular manner, for
        // person at last place has right neighbour at
        // placeholder 0. So we are taking modulo to make it
        // circular
        pos %= a.size();
        // Killing the person at placeholder 'pos'
        // To do that we simply remove that element
        a.erase(a.begin() + pos);
        // There is no need to increment the pos again to
        // pass the gun Because by erasing the element at
        // 'pos', now next person will be at 'pos'.
    }
 
    // Print Person that survive the game
    cout << a[0];
 
    return 0;
}


Java
// Java program for the above approach
import java.io.*;
import java.util.Arrays;
 
class GFG {
 
    // Driver code
    public static void main (String[] args) {
        int person = 100;
     
        // Placeholder array for person
        int[] a = new int[person];
     
        // Assign placeholders from 1 to N (total person)
        for (int i = 0; i < person; i++) {
            a[i] = i + 1;
        }
     
        // Will start the game from 1st person (Which is at
        // placeholder 0)
        int pos = 0;
     
        // Game will be continued till we end up with only one
        // person left
        while (a.length > 1)
        {
           
            // Current person will shoot the person next to
            // him/her. So incrementing the position.
            pos++;
           
            // As person are standing in circular manner, for
            // person at last place has right neighbour at
            // placeholder 0. So we are taking modulo to make it
            // circular
            pos %= a.length;
           
            // Killing the person at placeholder 'pos'
            // To do that we simply remove that element
            int[] anotherArray = new int[a.length - 1];
            System.arraycopy(a, 0, anotherArray, 0, pos);
            System.arraycopy(a, pos + 1, anotherArray, pos,a.length - pos - 1);
            a = anotherArray;
           
            // There is no need to increment the pos again to
            // pass the gun Because by erasing the element at
            // 'pos', now next person will be at 'pos'.
        }
     
        // Print Person that survive the game
        System.out.println(a[0]);
    }
}
 
// This Code is contributed by ShubhamSingh10


Python3
person = 100
 
# Placeholder array for person
a = [0] * person
 
# Assign placeholders from 1 to N (total person)
for i in range(person):
    a[i] = i + 1
     
# Will start the game from 1st person (Which
# is at placeholder 0)
pos = 0
 
# Game will be continued till we end up with
# only one person left
while (len(a) > 1):
     
    # Current person will shoot the person next
    # to him/her. So incrementing the position.
    pos += 1
     
    # As person are standing in circular manner,
    # for person at last place has right neighbour
    # at placeholder 0. So we are taking modulo
    # to make it circular
    pos %= len(a)
     
    # Killing the person at placeholder 'pos'
    # To do that we simply remove that element
    del a[pos]
     
    # There is no need to increment the pos again to
    # pass the gun Because by erasing the element at
    # 'pos', now next person will be at 'pos'.
 
# Driver code
 
# PrPerson that survive the game
print(a[0])
 
# This code is contributed by ShubhamSingh10


C#
// C# program for the above approach
using System;
using System.Linq;
 
public static class GFG
{
   
    // Driver code
    static public void Main ()
    {
     
        int person = 100;
     
        // Placeholder array for person
        int[] a = new int[person];
     
        // Assign placeholders from 1 to N (total person)
        for (int i = 0; i < person; i++) {
            a[i] = i + 1;
        }
     
        // Will start the game from 1st person (Which is at
        // placeholder 0)
        int pos = 0;
     
        // Game will be continued till we end up with only one
        // person left
        while (a.Length > 1)
        {
           
            // Current person will shoot the person next to
            // him/her. So incrementing the position.
            pos++;
           
            // As person are standing in circular manner, for
            // person at last place has right neighbour at
            // placeholder 0. So we are taking modulo to make it
            // circular
            pos %= a.Length;
           
            // Killing the person at placeholder 'pos'
            // To do that we simply remove that element
            a = a.Where((source, index) =>index != pos).ToArray();
           
            // There is no need to increment the pos again to
            // pass the gun Because by erasing the element at
            // 'pos', now next person will be at 'pos'.
        }
     
        // Print Person that survive the game
        Console.Write(a[0]);
    }
}
 
// This Code is contributed by ShubhamSingh10


Javascript


输出
73