问题
定义
- 让我们将自然数定义为数字系统中设置的数字
N
的可写数(WN),如果它可以从使用每个成员不超过一次的成员中写入该数字系统。'书面'的更严格定义:- 这里意味着连接。M
U
CONCAT
- 让我们将自然数定义为数字系统中符号集
N
的连续可实现数(CAN),如果它是 and 的 WN 数并且也是 and的CAN 数(另一个定义可能是 CAN并且如果所有数字都是WN和)。更严格:M
U
M
N-1
U
M
N
U
M
0 .. N
U
M
问题
让我们有一组S
自然数:(我们将零视为自然数)和自然数M
, M>1
。问题是找到给定的最大 CAN (MCAN)U
和M
。给定的集合U
可能包含重复项- 但每个重复项不能多次使用,原因(即如果U
包含 {x, y, y, z} - 那么每个重复项y
可以使用 0 次或 1 次,因此y
可以使用 0..共 2 次)。也U
期望在M
-numeral 系统中有效(即不能包含符号8
或9
任何成员 if M=8
)。而且,当然,成员U
是数字,而不是符号M
(所以对11
M=10
) - 否则问题将是微不足道的。
我的方法
我现在想到了一个简单的算法,它只是通过以下方式检查当前号码是否为 CAN:
- 检查
0
给定的 WNU
和M
? 转到 2:我们完成了,MCAN 为空 - 检查
1
给定的 WNU
和M
? 转到 3:我们完成了,MCAN 是0
- ...
因此,该算法正在尝试构建所有这些序列。我怀疑这部分可以改进,但可能吗?现在,如何检查号码是否为 WN。这也是某种“替代蛮力”。我已经意识到M=10
(事实上,因为我们正在处理字符串,任何其他M
都不是问题)PHP函数:
//$mNumber is our N, $rgNumbers is our U
function isWriteable($mNumber, $rgNumbers)
{
if(in_array((string)$mNumber, $rgNumbers=array_map('strval', $rgNumbers), true))
{
return true;
}
for($i=1; $i<=strlen((string)$mNumber); $i++)
{
foreach($rgKeys = array_keys(array_filter($rgNumbers, function($sX) use ($mNumber, $i)
{
return $sX==substr((string)$mNumber, 0, $i);
})) as $iKey)
{
$rgTemp = $rgNumbers;
unset($rgTemp[$iKey]);
if(isWriteable(substr((string)$mNumber, $i), $rgTemp))
{
return true;
}
}
}
return false;
}
- 所以我们正在尝试一件,然后检查其余部分是否可以用递归来编写。如果它不能被写入,我们正在尝试下一个成员U
。我认为这是可以改进的一点。
细节
如您所见,一种算法正在尝试构建之前的所有数字N
并检查它们是否为 WN。但唯一的问题是 - 找到 MCAN,所以,问题是:
- 可能是建设性算法在这里过度?如果是,还有哪些其他选项可以使用?
- 是否有更快速的方法来确定给定的数字是否为 WN
U
和M
?(如果前一点有肯定的答案,这一点可能没有意义,我们不会建立和检查之前的所有数字N
)。
样品
U = {4, 1, 5, 2, 0} M = 10
然后 MCAN = 2(无法达到 3)
U = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11} M = 10
然后 MCAN = 21(之前都可以达到,因为总共22
没有两个2
符号)。