n只猴子要選猴王,全部的猴子按照1,2,........n編號圍成一圓,從第1還開始按1,2,....m報數,凡是報m的猴子退出圈外,如此循環直到圈內剩下一隻猴子,這隻猴子就是猴王。
5只猴子分一堆桃子,怎麼也不能分紅5等份,只好先去睡覺,準備次日再分。夜裏1只猴子偷偷爬起來,先吃掉1個桃子,而後將其分紅5等份,藏起本身的一份就去睡覺了;第2只猴子又爬起來,吃掉1個桃子後,也將桃子分紅5等分,藏起本身的一份睡覺去了;之後的3只猴子都前後照此辦理。問最初至少有多少個桃子?
static void Main(string[] args)
{
SharePeech();
List<string> source = new List<string>() { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L" };
Console.WriteLine("猴王是:{0}", MatchMonkeyKing(source, 4));
Console.ReadLine();
}
/// <summary>
/// 選猴王
/// </summary>
/// <param name="source">有被選舉權的猴子</param>
/// <param name="reportCount">報數週期</param>
/// <returns>猴王</returns>
private static string MatchMonkeyKing(List<string> source, int reportCount)
{
int reportRound = 1;
int selectIndex = 0;
Console.WriteLine("猴子出局順序:");
while (source.Count != 1)
{
//踩雷的猴子出局,下一個猴子頂替他的位置從新報號(即下標不變),不然下個猴子報號
if (reportRound == reportCount)
{
Console.WriteLine("\t{0}", source[selectIndex]);
source.RemoveAt(selectIndex);
reportRound = 1;
}
else
{
selectIndex++;
reportRound++;
}
//若是這個猴子已是一輪最後一個,接他後面報數的猴子則從新回到開始報數的猴子
if (selectIndex == source.Count)
{
selectIndex = 0;
}
}
return source[0];
}
private static void SharePeech()
{
bool result = false;
int index = 1;
while (!result)
{
result = GetShareResult(++index, 0);
}
Console.WriteLine("最少須要{0}只桃", index);
Console.ReadLine();
}
/// <summary>
/// 剩餘桃子是否能平分
/// </summary>
/// <param name="total">猴子吃掉一隻,藏下一份後剩餘的桃子總數</param>
/// <param name="round">第幾只猴子來偷桃</param>
/// <returns>能被平分返回True,不能則返回False</returns>
private static bool GetShareResult(int total, int round)
{
round++;
int afterEat = total - 1;
//剩餘的桃保證每隻猴都有桃,而且能被均分
if (afterEat / 5.0 >= 1 && afterEat % 5 == 0)
{
if (round == 5) return true;
int afterHidden = afterEat / 5 * 4;
//下一隻猴以本次剩餘桃子總數再作偷吃偷藏
return GetShareResult(afterHidden, round);
}
return false;
}