1.猴子选大王(约瑟夫环)
一群猴子排成一圈,按1,2,…,n依次编号。然后从第1只开始数,数到第m只,把它踢出圈,从它后面再开始数,再数到第m只,在把它踢出去…,如此不停的进行下去,直到最后只剩下一只猴子为止,那只猴子就叫做大王。要求编程模拟此过程,输入m、n,输出最后那个大王的编号
function king($n,$m){
$mokey = range(1, $n);
$i = 1;
while (count($mokey) >1) {
$head = array_shift($mokey);//一个个出列最前面的猴子
if ($i % $m !=0) {
#如果不是m的倍数,则把猴子返回尾部,否则就抛掉,也就是出列
array_push($mokey,$head);
}
$i++;
}
return $mokey[0];
}
// 测试
echo king(10,7);
2.排列组合
有1、2、3、4···n个数字,能组成多少个互不相同且无重复数字的m位数?都是多少?
function arrange($n,$m) {
if ($n < $m) {
return [];
}
$data = [];
$arr = range(1, $n);
$data = arrange_rec($data, $arr, $m, '');
return $data;
}
//递归函数
function arrange_rec($data, $arr, $m, $str = '') {
foreach($arr as $k => $v) {
$res = $arr;
$s = round($m - 1);
$str1 = '';
$str1 .= $str.$res[$k];
if ($s > 0) {
unset($res[$k]);
$data = arrange_rec($data, $res, $s, $str1);
} else {
array_push($data, $str1);
}
}
return $data;
}
//测试
$data = arrange(6,3);
echo count($data);
echo '<pre>';
print_r($data);
3.偷苹果
有5个人偷了一堆苹果,准备在第二天分赃。晚上,有一人遛出来,把所有菜果分成5份,但是多了一个,顺手把这个扔给树上的猴了,自己先拿1/5藏了。没想到其他四人也都是这么想的,都如第一个人一样分成5份把多的那一个扔给了猴,偷走了1/5。第二天,大家分赃,也是分成5份多一个扔给猴了。最后一人分了一份。问:共有多少苹果?
class shareApples{
private $apple_quantity; //苹果总数量
private $men_quantity; //总人数
public function __construct(int $men_quantity) {
$this->men_quantity = $men_quantity;
$this->apple_quantity = 0;
}
/**
* 递归检查苹果数量是否符合要求
* @param int $total 苹果数量
* @param int $num_left 剩余苹果数量
* @param int $seq 现在是第几个人
*/
public function share(int $total, int $num_left, int $seq=1){
$men_quantity = $this->men_quantity;
if($seq <= $men_quantity && $num_left % $men_quantity == 1){
$num_left2 = $num_left - (int)($num_left/$men_quantity) -1;
if($num_left2 % $men_quantity == 1) {
if($seq == $men_quantity){
$this->apple_quantity = $total;
return true;
}else {
return $this->share($total, $num_left2, $seq + 1);
}
}
}
return false;
}
public function calc(){
for($i=1; ; $i++) {
$rt = $this->share($i, $i, 1);
if($rt === true){
$this->apple_quantity = $i;
return $i;
}
}
}
}
//测试
$m = new shareApples(5);
echo "苹果总数: ".$m->calc().PHP_EOL;