【问题】n只猴子选大王,选举办法如下:从头到尾1,2,3报数,凡报3的退出,余下的从尾到头1,2,3报数,凡报3的退出...如此类推,当剩下两只猴子时,取这时报1的为王,若想当猴王,请问当初应占据什么位置?
【测试数据】
n │ 7 │ 10│20│100 │
位置│2 │ 8│16│ 77 │
【参考程序1】
const number=3;
var n,num,i,total:integer;
a:array[1..100]of boolean; order:boolean;
begin
writeln('input n:');
readln(n);
total:=n; {队伍中剩下的猴子数}
for i:=1 to n do a[i]:=true;
repeat
order:=true; {order=true:顺序报数}
num:=0; {num:报的数字}
for i:=1 to n do {顺序报数}
if a[i] then begin {第i只在队列中才有资格报数}
num:=num+1;
if (num=number) then begin {如果为3}
a[i]:=false;total:=total-1; {出队,且猴子数少1}
num:=0; {num置0,又准备从1报起}
end;
end; {报到尾}
if total>number-1 then order:=false; {如还要继续报,则从尾到头}
num:=0; {从尾到头时,order=false}
for i:=n downto 1 do {逆向报数}
if a[i] then begin {在队列中}
num:=num+1;
if (num=number) then begin
a[i]:=false;total:=total-1;
num:=0;
end;
end;
until total=number-1; {直到剩下2只}
if not order then for i:=1 to n do if a[i] then begin
{报剩2只时,如上一次为从尾到头报数,则猴王为从头到尾报的第一只}
writeln('The Monkey King is :',i);readln;halt;end;
if order then for i:=n downto 1 do if a[i] then begin
{报剩2只时,如上一次为从头到尾报数,则猴王为从尾到头报的第一只}
writeln('The Monkey King is :',i);readln;halt;end;
end.
【参考程序2】 程序1中,用了order来记录是顺序还是逆序报数,不太方便。现简化之,取消了order,而在每一次报数前都判断是否只剩2只。
const number=3;
var n,num,i,total:integer; a:array[1..200]of boolean;
begin
writeln('input n:');
readln(n);
total:=n;
for i:=1 to n do a[i]:=true;
repeat
num:=0;
for i:=1 to n do
if a[i] then begin
if total=2 then begin writeln('he is :',i); readln;halt;end;
num:=num+1;
if (num=number) then begin
a[i]:=false;total:=total-1;
num:=0;
end;
end;
num:=0;
for i:=n downto 1 do
if a[i] then begin
if total=2 then begin writeln('he is :',i); readln; halt;end;
num:=num+1;
if (num=number) then begin
a[i]:=false;total:=total-1;
num:=0;
end;
end;
until total<number-1;
end.