谜题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