1:100盏灯开关:
大厅里有100盏灯,每盏灯都编了号码,分别为1-100。每盏灯由一个开关来控制。(开关按一下,灯亮,再按一下灯灭。开关的编号与被控制的灯相同。)开始时,灯是全灭的。现在按照以下规则按动开关。
第一次,将所有的灯点亮。
第二次,将所有2的倍数的开关按一下。
第三次,将所有3的倍数的开关按一下。
以此类推。第N次,将所有N的倍数的开关按一下。
问第100次按完以后,大厅里还有几盏灯是亮的。
// 方法1:双重for循环,外层控制,第1次...第100次;内层控制100盏灯;每次中,从1到100盏灯哪些灯发生变化;
$arr = array_fill(1,100,0); // 构造100盏灯; 初始:等全部灭的,用0代替; 0表示灯灭;
$cishu = 1;
for($cishu = 1;$cishu<=100;){ // 从第一次到第100次;
for($i = 1;$i<=100;$i++){ // 从第1盏灯到第100盏灯;
if($i%$cishu==0){ // 从100盏灯中依次找出,判断找出符合改变状态的灯;
$arr[$i] = ~($arr[$i]); // 改变 符合条件的灯 的状态。 (注意:0取反的结果是-1,-1再取反又是0);
}
}
$cishu++; // 第$cishu次运行结束,再循环$cishu+1次,根据条件,改变每盏灯的变化;
}
for($i = 1;$i<=100;$i++){
if($arr[$i]==-1){ // 0的取反是-1;所以状态是-1的时候,表示灯在亮着;
echo $i;
echo '<br/>';
}
}
// 方法2:外层循环依旧用for循环来逐一运行每一次; 内层循环利用foreach,遍历出每盏灯的健名和状态(值);
$arr = array_fill(1,100,0); // 构造100盏灯; 初始:等全部灭的,用0代替; 0表示灯灭;
$cishu = 1;
for($cishu = 1;$cishu<=100;$cishu++){
foreach($arr as $keys => $values){
if($keys%$cishu==0){
//① :$arr[$keys] = ($values==0)?1:0; 三目运算的方法:(成不成立?1:0)
$arr[$keys] = $values ^ 1; //异或(位)运算; (0^1==1;1^1==0); ②;
//③ : arr[$keys] = $values+1 // 每次的值(状态)都加1,(0关,1开,2关,3开,4关,5开,6关...最后被2整数余1的表示状态 开);
/*** ④ **
条件判断,赋值改变法;类似于 上面的三目运算;
if($values==0){
$arr[$keys] = 1;
}else{
$arr[$keys] = 0;
}
********/
}
}
}
foreach($arr as $keys=>$values){
if($values==1){
echo $keys.'====>'.$values;//(值表示状态,都为1表示开着,健名表示灯的标号,哪些标号的灯开着最后);
echo '<br/>';
}
}
2:逢三退一:
有10个人(编号1-10) 围成一个圈 从第一个开始数 数到三 踢出这个人 然后接着往下循环数! 直到剩下一个人为止! 问最后剩下的那个人的编号是几?
// 方法1 :假设原先有10个人,都为true,数到3的时候,那个人变为false,最后剩余的那个true就为所求的;
$tenarr = array_fill(1,10,true); // 构造10个人,初始都标识为true;
$jishu = 0; // 计数初始为0,数到3后,再重新开始;
$keys = 1; // 数组下标初始为1,到10结束;
$truegeshu = count($tenarr); // 标识为true的个数,初始为10,数到3的时候,减一;
while($truegeshu>1){
if($tenarr[$keys]==true){ // 如果标识是ture,说明还在圈中;
$jishu++;
if($jishu==3){ //数到3的时候;
$jishu = 0; // 重新下一次计数,初始;
$tenarr[$keys]=false; // 将标记true变成false; 退出;
$truegeshu--; // 标识为true的个数少一个;
}
}
$keys++; // 进入下一个数;
if($keys>count($tenarr)){ // 如果下标的值,大于总个数的时候,(从1开始的,即:$keys>10);
// $keys=count($tenarr)+1
$keys = 1; // 假如下标数到11的时候,超过了10个总数,从1继续开始;
}
}
foreach($tenarr as $ks=>$vs){
if($vs==true){
echo $ks; // 4; 数组的下标从1开始设置并计算的;
}
}
// 方法2 :利用php数组特性处理;
$arr2 = range(1,10); //构造一个数组,值代表10个人以及对应的编号;
$jishu = 0; // 计数器;初始为0,到3还原;
while(count($arr2)>1){
foreach($arr2 as $keys=>$values){
$jishu++;
if($jishu==3){
unset($arr2[$keys]); // 直接从数组中,剔除出去;
$jishu = 0;
}
}
}
print_r($arr2); // Array ( [3] => 4 ); 原数组中,只剩1个数值;
// 方法3: 利用aarray_splice()函数去除,改变原数组的值以及下标;(只去除,没有替换);
$arr3=array('1','2','3','4','5','6','7','8','9','10');
function leftOne($arr) {
$num = count($arr);
$count = 0;
for ($j = 0; $j < $num; $j++) {
$count++;
$diff = count($arr);
if (2*$count >= $diff) {
array_splice($arr, 2*$count - $diff, 1);
$count = 0;
}else {
array_splice($arr, 2*$count, 1);
}
}
return $arr[0];
}
echo leftOne($arr3);
3:小球落地:
一球从100米高度自由落下,每次落地后反跳回原高度的一半,再落下,求它在第10次落地时,共经历多少米,第10次反弹多高?
$s = 100; // 第一次从100米开始落地;
$h = 50; // 从反弹的高度h=50开始,一个周期为 2*h;
for($i=2;$i<=10;$i++){ // 从第一次落地后反弹,到第二次落地是一个循环周期; 反弹的高度$h = 50;
$s = $s+2*$h;
$h = $h/2;
}
echo $s;
echo $h;
4:取各不相同的牌:
有9张牌每张是不一样的,在里面任意取3张,且3张牌中各不相同,一共有多少种取法?
$kk= 0;
for($i = 0;$i<=8;$i++){
for($j = $i;$j<=8;$j++){
for($k = $j;$k<=8;$k++){
if(($i!=$j)&&($j!=$k)&&($i!=$k)){
$kk++;
}
}
}
}
echo $kk;
5:乒乓比赛匹配:
两个乒乓球队进行比赛,各出三人。甲队为a,b,c三人,乙队为x,y,z三人。已抽签决定比赛名单。有人向队员打听比赛的名单。a说他不和x比,c说他不和x,z比,请编程序找出三队赛手的名单。
for($i = 1;$i<=3;$i++){ // $i a的对手,从xyz(1,2,3)中选其中一个;
for($j = 1;$j<=3;$j++ ){ // $j b的对手,从xyz(1,2,3)中选其中一个;
for($k = 1;$k<=3;$k++){ // $k b的对手,从xyz(1,2,3)中选其中一个;
if(($i!=1)&&($k!=1)&&($k!=3)&&($i!= $j)&&($i!= $k)&&($j!= $k)){ // 还需要保证 abc的对手不能有相同的,(一个人不能参加两场比赛);
echo 'a'.'-----'.$i; // a-----3;
echo 'b'.'-----'.$j; // b-----1;
echo 'c'.'-----'.$k; // c-----2;
}
}
}
}
6:猴子搬香蕉:
一只猴子旁边有100根香蕉,猴子离家50米;一次最多搬50根香蕉;但猴子每走1米就要吃掉1根香蕉,问猴子最多能拿回家多少香蕉?
$xiangjiao = 100;
for($juli =1;$juli<=50;$juli++){
if($xiangjiao>=50){
$xiangjiao -= 3;
}else{
$xiangjiao -= 1;
}
echo '走到第'.$juli.'米时','香蕉剩余'.$xiangjiao;
echo '<br/>';
}
7:规律数字求和:
一组数字 1,1,2,3,5,8,13.........求其前20项的和;
// 方法1:利用迭代、替换求和;
$a = 1;
$b = 1;
$s = 2;
$m = 0;
for($i=3;$i<=20;$i++){
$m = $a+$b;
$s = $s+$m;
$a = $b;
$b = $m;
}
echo $s; // 17710;
// 方法2:利用函数递归,得出每一项的值,然后求和;
function qiuhe($n){
if($n>2){
return qiuhe($n-1)+qiuhe($n-2);
}
if($n=2){
return 1;
}
if($n=1){
return 1;
}
}
$sum = 0;
for($i=1;$i<=20;$i++){
$sum += qiuhe($i);
}
echo $sum; // 17710;
// 方法3:利用数组,算出每个元素的值,然后求和;
$arr[0] = $arr[1] = 1;
for($i=2;$i<20;$i++){
$arr[$i] = $arr[$i-1] + $arr[$i-2];
}
echo array_sum($arr); // 17710;
8:百钱白鸡:
公鸡5文钱一只,母鸡3文钱一只,小鸡3只一文钱,用100文钱买一百只鸡,其中公鸡,母鸡,小鸡都必须要有,问公鸡,母鸡,小鸡要买多少只刚好凑足100文钱。
for($x=1;$x<20;$x++){ // 公鸡x只;
for($y=1;$y<34;$y++){ // 母鸡y只;
$z = 100- $x - $y; // 母鸡z只;
if((5*$x + 3*$y + $z/3) == 100){
echo '公鸡'.$x.'只'.' '.'母鸡'.$y.'只'.' '.'小鸡'.$z.'只'.' ';
echo '<br/>';
}
}
}
8:过路口问题:
假设某人有100,000现金。每经过一次路口需要进行一次交费。交费规则为当他现金大于50,000时每次需要交5%如果现金小于等于50,000时每次交5,000。请写一程序计算此人可以经过多少次这个路口。
// while循环方法;
$money = 100000;
$lukou = 0;
while($money > 5000){
if($money > 50000){
$money *= 0.95;
}else{
$money -= 5000;
}
$lukou++;
echo '过了'.$lukou.'个路口','钱还剩于'.$money;
echo '<br/>';
}
// for循环方法; for(初始化;循环语句;执行循环后语句)
for($money = 100000,$num=0;$money >= 5000;$num++) {
if($money > 50000) {
$money *= 0.95; // 扣了5%,即原来的0.95倍
} else {
$money -= 5000;
}
}
echo $num;
9:猴子吃桃问题:
猴子第一天摘下若干个桃子,当即吃了一半,还不过瘾,又多吃了一个第二天早上又将剩下的桃子吃掉一半,又多吃了一个。以后每天早上都吃了前一天剩下的一半零一个。到第10天早上想再吃时,见只剩下一个桃子了。求第一天共摘了多少。
// 方法1:
// 第一天摘了$i个桃子; 然后从1开始,寻找满足条件的;
for($i = 1;;$i++){
$y = $i;
for($d = 1; $d < 10;$d++){
$y = $y/2 - 1;
}
if($y == 1){
break;
}
}
echo $i; // 1534;
echo '<hr/>';
// 方法2: 第10天剩余1个,第9天的时候开始剩余4个(吃了3个);第8天的时候开始剩余10个(吃了6个);...
$sheng = 1;
for($i = 9;$i > 0;$i--){
$sheng = 2*($sheng+1);
}
echo $sheng; // 1534;
9:人分苹果问题:
有5个人偷了一堆苹果,准备在第二天分赃。晚上,有一人遛出来,把所有菜果分成5份,但是多了一个,顺手把这个扔给树上的猴了,自己先拿1/5藏了。没想到其他四人也都是这么想的,都如第一个人一样分成5份把多的那一个扔给了猴,偷走了1/5。第二天,大家分赃,也是分成5份多一个扔给猴了。最后一人分了一份。问:共有多少苹果?
for ($i = 1; ; $i++)
{
if ($i%5 == 1) {
//第一个人取五分之一,还剩$t
$t = $i - round($i/5) - 1;
if($t % 5 == 1)
{
//第二个人取五分之一,还剩$r
$r = $t - round($t/5) - 1;
if($r % 5 == 1)
{
//第三个人取五分之一,还剩$s
$s = $r - round($r/5) - 1;
if($s % 5 == 1)
{
//第四个人取五分之一,还剩$x
$x = $s - round($s/5) - 1;
if($x % 5 == 1)
{
//第五个人取五分之一,还剩$y
$y = $x - round($x/5) - 1;
if ($y % 5 == 1) {
echo $i;
break;
}
}
}
}
}
}
}
9:进制转换问题:
给两个参数,一个整数值A,代表需要转换的数字,一个整数B,代表返回值的宽度,要求获得,整数A的十六进制字符串,如果宽度不够B,那么前面用0补齐.
function dectohex($a,$b){
$arryu = array();
for(;;){
$yu = $a % 16;
if($yu<10){
$arryu[] = $yu;
}else{
$temp = array('A','B','C','D','E','F');
$arryu[] = $temp[($yu - 10)];
}
$a = floor($a/16);
if($a == 0){
break;
}
}
$strs = strrev(implode($arryu));
$strlen = strlen($strs);
if($strlen < $b){
for($i=0;$i<$b-$strlen;$i++){
$strs = '0'.$strs;
}
}
// 1、可以直接用str_pad函数来实现填充;
// 2、也可以,数组先不转换成字符串,先在数组中追加到指定的长度,最后再转换成字符串,反转;
return $strs;
}
echo dectohex(170,8)