今遇到一个小学数学题, "各位数字互不相同,且能被自身每个数字整除的最大五位数是多少", 想来想去只有各种试, 后面绝对麻烦, 就想着用代码来直接试, 就百度了一个排列组合的算法.
1. 符合题干的整数, 百度得以下结论
若一个整数的末位是0、2、4、6或8,则这个数能被2整除。
若一个整数的数字和能被3整除,则这个整数能被3整除
若一个整数的末尾两位数能被4整除,则这个数能被4整除
若一个整数的末位是0或5,则这个数能被5整除
若一个整数能被2和3整除,则这个数能被6整除
若一个整数的个位数字截去,再从余下的数中,减去个位数的2倍,如果差是7的倍数,则原数能被7整除。如果差太大或心算不易看出是否7的倍数,就需要继续上述「截尾、倍大、相减、验差」的过程,直到能清楚判断为止。例如,判断133是否7的倍数的过程如下:13-3×2=7,所以133是7的倍数;又例如判断6139是否7的倍数的过程如下:613-9×2=595 , 59-5×2=49,所以6139是7的倍数,余类推
若一个整数的末尾三位数能被8整除,则这个数能被8整除
若一个整数的数字和能被9整除,则者个整数能被9整除
若一个整数末位时0,则这个数能被10整除
所以N是一个各位数字互不相等的自然数, 即N这个数可能是有0,1,2,3,4,5,6,7,8,9,0这几个数中的数字组成。且它能被它的每个数字整除。那么N这个数字中不能含有0,因为0不能作除数。由于N中没有0,那么5和偶数(2,3,6,8)不能同时存在。所以N中没有5。则N这个数字可以由含有1,2,3,4,6,7,8,9这些数字中的数字组成。又因为1+2+3+4+6+7+8+9=40,那么1,2,3,4,6,7,8,9这8个数字组成的数不能被9整除。那么要使N能被9整除,且保证N最大,那么就去掉数字4。则N由1,2,3,6,7,8,9组成。要使N能被7整除,则N这个整数的个位数字截去,再从余下的数中,减去个位数的2倍,如果差是7的倍数,则原数能被7整除。且N要被8整除。那么最后一位必须要为偶数。那么最后一位只能为2、6、8中的一位。
所以符合题目要求的是 1,2,3,6,7,8,9
2. 进行排列组合, 计算符合要求的数字组合
以下是度娘到的来自 CSDN song5198038_1 的<PHP排列组合算法>
<?php
// 阶乘
function factorial($n) {
return array_product(range(1, $n));
}
// 排列数
function A($n, $m) {
return factorial($n)/factorial($n-$m);
}
// 组合数
function C($n, $m) {
return A($n, $m)/factorial($m);
}
// 排列
function arrangement($a, $m) {
$r = array();
$n = count($a);
if ($m <= 0 || $m > $n) {
return $r;
}
for ($i=0; $i<$n; $i++) {
$b = $a;
$t = array_splice($b, $i, 1);
if ($m == 1) {
$r[] = $t;
} else {
$c = arrangement($b, $m-1);
foreach ($c as $v) {
$r[] = array_merge($t, $v);
}
}
}
return $r;
}
// 组合
function combination($a, $m) {
$r = array();
$n = count($a);
if ($m <= 0 || $m > $n) {
return $r;
}
for ($i=0; $i<$n; $i++) {
$t = array($a[$i]);
if ($m == 1) {
$r[] = $t;
} else {
$b = array_slice($a, $i+1);
$c = combination($b, $m-1);
foreach ($c as $v) {
$r[] = array_merge($t, $v);
}
}
}
return $r;
}
// ====== 测试 ======
$a = array("A", "B", "C", "D");
$r = arrangement($a, 2);
var_dump($r);
$r = A(4, 2);
echo $r."n";
$r = combination($a, 2);
var_dump($r);
$r = C(4, 2);
echo $r."n";
根据算法列出符合要求的组合, 并求最大值
<?php
$res = arrangement($arr, 5);
$nums = [];
foreach ($res as $value) {
$number = 0;
foreach ($value as $key => $val) {
$number += $val * pow(10, $key);
}
$nums[] = $number;
}
var_dump(count($nums));
$nm = [];
foreach ($nums as $value) {
if ($value % 2 != 0) {
continue;
} else {
$sval = strval($value);
$sarr = str_split($sval);
$ns = 0;
foreach ($sarr as $val) {
// echo $value . " % " . intval($val) . "=" . ($value % intval($val))."n";
$ns += $value % intval($val);
}
if ($ns == 0) {
$nm[] = $value;
}
}
}
var_dump(count($nm)); // 28
var_dump($nm); // [.....]
var_dump(max($nm)); // 98136
3. 其他解决题目思路
首先数字各不相同,且要求最大,则可以考虑万位和千位是98
其次这个数是9的倍数,看数字之和,8的倍数看后三位,那么可以枚举8的倍数
如果这个数是9的倍数,前两位的数字之和是17,那么后三位数字之和可能是1,10,19….
剩下的1,2,3,6,7组合最大的三位数是16, 最小为6, 那么这三位数字和应该是 10, 很明显这三个数为 1,3,6
那么这个五位数就有两个可能98136, 98316(尾数必须为偶数). 代入计算符合要求的是 98136
很赞哦! ( 1 )