关于数学问题



主题论坛上定期出现的关于程序员是否需要数学的争论长期以来一直是圣战的普遍领域。 在边界将善与恶分离的我们的(右侧)边界上,我想分享一个例子,清楚地说明需要多少,甚至(我们不会害怕这个词)。

考虑一个有趣的编程问题,它具有奥林匹克特征。

Pnp:从现在开始,支持当今编程由精美设计的网页组成的想法的支持者可以停止阅读,这是绝对正确的,您不需要数学...

好吧,您不必坚持这一点,您不比我们更糟,您的工作非常重要,因为我已经同意我们对编程有不同的想法...

是的,您是完全正确的,这些奥林匹克竞赛将无法在最后一个框架的帮助下在一行代码中绘制七条红色的垂直线...

尽管如此,我认为这是我的想法是正确的(这是高度组织化物质以蛋白质形式存在的致命特性),因此我将在其支持下提出论点。

我提出了一个问题-如果需要用国际象棋骑士在按键周围移动,可以在电话键盘(键盘)上键入以给定的p按钮结尾的长度K的多少个不同的数字。 据了解,您看到了键盘(我仍然有普通的手机,而不是智能手机,所以我每天都看到它,更高级的阅读器应该与Internet联系以寻求帮助),并且您知道棋马如何行走(很容易用Google搜索)。 到目前为止,如果您不具备计算期权的能力,则数学与之无关。

第一个解决方案非常明显-我们将所有10个按钮一个接一个(为了普遍起见,我们用n表示它们的数量),考虑所有可能的长K数,然后计算在所需按钮上结束的数字。 汇总得出的数字并准备好答案。 已查看选项的总数大致表示为n * B(K),其中B(K)是长度为K的可能移动数。实际上,您需要考虑n个位置的总和,因为B(p,K)显然取决于按钮的数量但作为第一个估计下降。

在继续搜索B之前,可以通过应用(尚不包括数学)常识来显着减少选项的数量。 由于按钮的移动取决于背景,因此我们可以反转任务,并从所需的p按钮开始查找所有长度为K的数字。 这样,选项的总数将为B(p,K),即少n倍。 哇,我们刚刚找到了一种加快解决方案搜索速度的方法10次-很酷,让我们看看还剩下多少。

我们需要评估B(p,K),为此我们确定在每一步中我们都有2到3个选项来开发事件。 随之而来的是(总的来说,这是组合的,但是从直观上讲是清楚的),选项的总数将为2 ** K到3 ** K(以下我将K-1用作K)。 我们甚至可以通过转移到概率模型来改进此估计。 考虑到目前每个按钮上都有手指存在的可能性相同(强有力的陈述,很可能是不正确的,但粗略的估计是可以接受的),我们可以计算平均移动选项数7 * 2 + 2(按钮4和6)* 3 = 20/9〜2.22 。 则估算值为2.22 ** K,并且我们肯定知道我们至少有2 **K。 然后对于K = 100,我们得到一个下界2 ** 100 =(2 ** 10)** 10>(10 ** 3)** 10 = 10 ** 30。

如果我们考虑一个纳秒的选择(即使在功能强大的台式PC上也不容易),那么我们需要10 ** 30/10 ** 9 = 10 ** 21秒。 接下来,我们回想起美妙的单调“π秒等于一个世纪”,所需时间将是10 ** 21 / 3.14 * 10 ** 9〜3 * 10 ** 11个世纪。 在我看来,很少有人会看到使用建议的方法进行计算的结尾。 参展商很糟糕,只有析因比她差。

我们将基于对选项的数量而不是选项本身感兴趣的事实来改进解决方案。 您可以提供明显的公式B(p,K)=所有p'的B(p',K-1)的和,我们从p中获得1个移动。 我们从最后一个按钮开始,并为其分配权重1,然后执行将当前权重求和到下一个权重的过程,重复至所需的深度。

我们以一个示例(以数字1 {1234567890}开头)来说明:
初始重量{1000000000},
首次转帐{0000010100}(2个选项)后,
在第二次转帐{2010001001}(5个选项)之后,
在第三个{0102040300}之后(10个选项),依此类推。

该算法很简单,甚至可以用手来实现。 执行时间的一般估计是K次迭代,每次迭代n个权重时,我们修改的n个相关权重不超过n个,总计n ** 2 *K。 对于前面考虑的情况,10 * 10 * 100 = 10 ** 4-相当多。

剩下的只是评估每个操作的持续时间-这是加法(垃圾问题),而不是简单的加法(从这个地方更详细)。 我们已经将响应的下限设置为2 ** K,也就是说,我们肯定至少需要K位来表示结果。 上限为3 ** K,对于我们的情况为3 ** 100 =(3 ** 5)** 20 <(2 ** 8)* 20 = 2 ** 160,也就是说,我们保证可以容纳160位。 我们可以假设128位就足够了,因为2.2 ** 100 <2 ** 128,但是接受这样一个关于信仰的声明很可怕,因此我们需要一个至少包含160位或49位十进制数字的数字,具体取决于您的数字库精度高。

PNP:不要提供浮点数,我们需要一个完全准确的结果。
在公认的假设下,加法运算将占用160/8 = 20个字节/ 4 = 5个32位长的整数的加法运算,这绝不会影响时间顺序(它在K中保持线性),但会显着增加实际计算时间(几倍)。

无论如何,结果简直都是宏伟的-我们将任务从在合理的时间内从根本上无法解决的问题变成了完全可以解决的问题:如果在微秒内执行一次基本加法运算(即使在Arduino板上也很容易确保),那么总时间不会超过10 ** 4 * 20 / 10 ** 6,不到一秒钟),而我们没有做任何数学运算。

但是,如果我们需要更大的K(当然是线性计算的阶数),这很好,但是对于大的值,它可能(并且将)导致大量的时间损失。 事实证明,您可以显着改善预期时间,多加注意。

我们在计算的每个步骤中所做的操作(伪代码):

  = 0;
   1
    2
*  (  1     2)
*       1     2.
  =  



    2 (  1 *  )

0 1, . '=* =(...((*)*)...). , =***. , . **3, ***3 — , ? , …

— , **3 , , , ( ) ( ), . , 100 99 8. , 2*log2(), ( =100 1000/10=100 ) , 2*log2()***3. , , , . , , log2(K), , , 100.

- ( , ), , , .

Source: https://habr.com/ru/post/zh-CN473460/


All Articles