对于初学者的一些定义:flip(n)是对七段显示字体编号进行180度旋转,因此七段字体中的2将被翻转为2。0、1、2、5、8将被映射到它们自己。6 -> 9,9 -> 6和3,4,7没有定义。因此任何包含3,4,7的数字都是不可翻转的。更多示例:flip(112) = 211, flip(168) = 891, flip(3112) = not defined.
(顺便说一下,我很确定flip(1)应该是未定义的,但作业上说flip(168) = 891所以对于这个作业,flip(1)是定义的)
最初的挑战:找到一个整数n> 0,满足以下三个条件:
- 定义了flip(n), flip(n) = n
- flip(n*n)被定义
- n能被2011整除-> n % 2011 == 0
我们的解决方案,你可以找到下面似乎工作,但它没有找到一个答案,至少不是2011年。如果我用1991代替(我搜索了一些可以解决问题的"基数"),我得到了一个非常快的答案,说1515151是一个。所以基本概念似乎是有效的,但不适合作业中给定的"基础"。我在这里错过了什么?
用伪代码编写的解决方案(我们在Small Basic中有一个实现,我在Java中做了一个多线程的):
for (i = 1; i < Integer.MaxValue; i++) {
n = i * 2011;
f = flip(n, true);
if (f != null && flip(n*n, false) != null) {
print n + " is the number";
return;
}
}
flip(n, symmetry) {
l = n.length;
l2 = (symmetry) ? ceil(l/2) : l;
f = "";
for (i = 0; i < l2; i++) {
s = n.substr(i,1);
switch(s) {
case 0,1,2,5,8:
r = s; break;
case 6:
r = 9; break;
case 9:
r = 6; break;
default:
r = "";
}
if (r == "") {
print n + " is not flippable";
return -1;
} elseif (symmetry && r != n.substr(l-i-1,1)) {
print n + " is not flip(n)";
return -1;
}
f = r + f;
}
return (symmetry) ? n : f;
}
从启发式的角度来看(通过最小的实验和主要的直觉),如果不优化你的搜索技术,你不太可能找到一个解决方案(例如,使用一种构造方法来构建一个不包含3,4,7的完全正方形,并且是可随意对称的)。而不是优化计算,这不会显著改变复杂性):
我将从满足2个条件的所有数的列表开始(这个数和它的翻转是相同的,即翻转对称,并且它是2011的倍数),小于10^11:
192555261 611000119 862956298988659886 2091001602 22205502222589226852 6510550159 858511585810282828201 12102220121 1806555908118551215581 19299066261 2086609980222582528522 25288188252 2551000155225862529852 28018181082 2856818958228806090882 50669869905 5190585061552218581225 55666299955 5860986098559226192265 60912021609 6865151598968828282889 69018081069 6956808956985065859058 85551515558 8928515826891081118016 92529862526 9285222582695189068156 95625052956 9605689509696592826596 98661119986 9888212888698986298686
那里有46个数字,根据2011的定义和倍数,都是可翻转对称的,小于10^11。满足这个条件的2011的倍数将变得越来越少,因为从统计上看,随着数字数量的增加,回文的倍数将越来越少。
。对于任何给定的范围,例如[1,10 ^11](如上所述),有46个。对于相邻的等宽范围:[10^11+ 1,2 *10^11],我们可能会猜测找到另外46或左右。但是,当我们继续以相同宽度的10的更高次幂为间隔时,数字的数量是相同的(因为我们分析的是相同宽度的间隔),尽管回文条件现在落在更多的数字上,因为数字的数量增加了。所以当回文数趋于无穷时我们期望在任意一个区间上回文数趋于0。或者,更正式地(但没有证明),对于每个正值N,概率为0的给定区间(预定宽度)将有超过N个2011的倍数是回文。
因此,我们可以找到的回文数将随着穷举搜索的继续而减少。根据对于任何找到的回文的正方形可以翻转的概率,我们假设回文的正方形是均匀分布的(因为我们没有分析告诉我们不是这样,也没有理由相信不是这样),那么任何给定的d位长度的正方形可以翻转的概率是(7/10)^d。
让我们从找到的最小的正方形开始
192555261 ^ 2 = 37077528538778121
已经有17位数字长了,所以它的概率大约是0.002。1/430)它的定义是可翻转的。但是当我们到达列表上的最后一个时:
98986298686 ^ 2 = 9798287327554005326596
,长度为24位,并且具有小于1/5000的可翻转定义的概率。
因此,随着搜索数量的增加,回文的数量减少,任何找到的回文方块可翻转的概率也减少-双刃剑。
剩下的就是找到某种密度比,然后看看找到解决方案的可能性有多大……尽管直觉上很清楚,从概率上讲,找到一个解决方案的可能性要小得多(这绝不排除存在一个甚至大量的解决方案(可能是无限个?))。
祝你好运!我希望有人能解决这个问题。与许多问题一样,解决方案通常不像在更快的机器上运行算法那样简单,或者使用更多的并行性,或者使用更长的时间等等,而是使用更先进的技术或更有创造性的方法来解决问题,这本身就进一步推动了该领域的发展。答案,一个数字,(通常)远不如推导它的方法有趣。
你正在搜索所有能被2011整除的数,然后检查它们是否是自身的翻转。但是当你得到7位数之后它本身是翻转的条件比它能被2011整除的条件更具限制性。所以我建议你迭代遍历所有没有数字3,4,7的数,然后构造一个把自己前置到自己的数,如果中间的数字是11,22,55或88,可能会压扁一个中间的数字。到2011年检验可除性,再检验n*n
是否可翻转。
要非常、非常注意n*n
会遇到整数溢出的可能性。当您达到基数的5位数字时,n
将是9或10位数字长,n*n
将是18-21位数字长。
不一定是一个完整的解决方案,更像是一个可以帮助你的思考过程。
- n = flip(n) => n是一个回文(在flip()中旋转180°),n仅由映射到flip()中的数字组成,即:0,1,2,5,8 定义
- 翻转(n*n)。因此n*n可能不包含3,4,7
- n % 2011 = 0.