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;
}