猴子的把戏
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; }