微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

以下代码背后的逻辑是什么?

如何解决以下代码背后的逻辑是什么?

我在codeforces.com上找到了此代码,但我对解决方案所涉及的逻辑感到困惑。 题: https://codeforces.com/contest/4/problem/A一个用户代码

print("YNEOS"[2**int(input())%24<9::2])

但是我使用了一种非常简单的蛮力方法。由于我是初学者并且自学成才,请向我彻底解释。谢谢。

解决方法

这里的答案实际上更多地是关于数学而不是Python,但是希望下面的解释会有所帮助。

首先,澄清一些Python基础知识:

print("YNEOS"[0::2]) # "YES"
print("YNEOS"[1::2]) # "NO"

此设置是代码争用中的一个相当普遍的技巧,目的是使代码尽可能短(且不可读)。从中可以看到,您发布的代码仅根据输入选择0还是1作为"YNEOS"字符串的起始索引。然后::2意味着得到第二个字母。

第二,您可能已经知道这一点,但是input()返回一个字符串,因此我们必须使用int(input())将其转换为整数。


现在是问题所在,那就是尝试将输入数字w分成两部分,两者都是偶数。两个偶数之和本身总是一个偶数,这意味着w是有效的解决方案,它必须是偶数。在编程中检查偶数的一种简单方法是检查数字modulo 2是否等于0。但是,在我们这种情况下,该数字也必须大于2,因为不能将2分解为两个偶数-大小一半。所以我们需要检查:

w % 2 == 0 and w > 2

稍加修改,在现实世界中,这将是解决问题的方法。我们不需要强力方法,因为问题不是问您哪种特定的组合是可能的,只有 any 组合是可能的。现在,我们需要更多的唯一理由就是使代码更短。我们该怎么做?

登录

最困难的部分是将w > 2合并到带有奇偶校验的一条语句中。尝试将w加2或将其乘以2或类似的方法是很诱人的,但这是行不通的,因为它只会移动输入数字的奇数模式。在w > 2之后,我们需要一些有关模式的测量(只需使用一个操作)即可更改

事实证明,使用2的幂将给出我们的答案。如果对从1到100的每个数字计算2到w的幂,则得到2,4,8,16,32,64,...。没什么特别的。但是,请回想一下模运算-我们如何使用它在前2个,3个或4个数字之后按此顺序获得不同的答案?

请注意,任意n之后(包括其后)中序列中的每个数字都是n的倍数:2,16是2的倍数。4,32是2的倍数。 4. 8,64是8的倍数,依此类推。因此,出于我们的目的,我们可以运行:

2**int(input()) % 8

对于每个输入(w)1-100,我们将得到2,...。进步!

但是现在由于我们序列中的每个数字都是2的幂,所以它们都是偶数。我们如何仅基于w来检查2**w是否为偶数?事实证明,我们可以检查2**w % 3。如果该数量等于1,则w是偶数。否则,w是奇数。 (这是一个有趣的结果。为什么2的每个幂与偶数的指数正好比3的倍数大1?)

首页伸展

现在我们快到了。我们可以通过检查((2**w % 8) + (2**w % 3)) == 1来组合我们的结果,但这效率极低,而且绝对不会缩短我们的代码。相反,我们可以将两个模数(8和3)彼此相乘得到24,并将其用作新的模数。 (2**w % 24)给出以下序列,从w = 1开始:

2,...

我们是如此接近!我们可以看到w的偶数值大于2的结果始终为16。因此,如果2**w % 24 == 16w是该问题的解决方案,则应返回“ YES”。否则,我们应该返回“ NO”。我们可以改成相反的说法:如果2**w % 24 != 16,则返回“ NO”,否则返回“ YES”。从这里开始,我们可以使用2**w % 24 < 9来保存一些字符,这是等效的,因为序列中不等于16的唯一值小于9。这是您的代码要做的最后一个选择,并记住它因为这有点令人困惑:如果2**w % 24 < 9True,我们想返回“ NO”。

最后一篇文章是了解Python internally treats True等于1,而False等于0。因此,例如,如果运行"YNEOS"[True],您将得到N,即索引1处的字符。这意味着"YNEOS"[2**int(input()) % 24 < 9::2]的不等式为"YNEOS"[1::2] == "NO"时将得出True,就像我们想要的那样。否则它将计算为"YNEOS"[0::2] == "YES"

因此,您已经拥有了它。现在,如果我已经足够好地解释了这一点,您就可以理解print("YNEOS"[2**int(input())%24<9::2])到底是做什么的。

PARTING WARNING

这是一种可爱的解决方案,但效率不高。 Python恰好擅长处理2**100之类的大数字,但在其他语言中,大的数字很可能会炸毁一个正则整数变量,甚至是C ++ 64位long long变量。另外,即使它不会爆炸,发现巨大的模数24在计算上也很昂贵。在这些“代码高尔夫”比赛之外的任何地方,如果您试图使代码尽可能短,那么您就不想使用这样的代码。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。