【问题标题】:Finding "decent" numbers algorithm reasoning?寻找“体面”的数字算法推理?
【发布时间】:2017-07-15 09:26:38
【问题描述】:

问题

夏洛克·福尔摩斯对他的大敌莫里亚蒂教授越来越偏执。他为制服莫里亚蒂所做的一切努力都是徒劳的。这些天,Sherlock 正在与 Watson 博士一起解决一个问题。 Watson 提到,最近 CIA 的超级计算机“The Beast”遇到了奇怪的问题。

今天下午,夏洛克收到了莫里亚蒂的来信,说他感染了“野兽”病毒。而且,那张纸条上还印着数字N。经过一番计算,Sherlock 发现清除病毒的关键是最大的 N 位“体面”数字。

一个“体面”的数字有 -

  • 3 或 5 或两者都作为其数字。
  • 不允许使用其他数字。
  • 3 出现的次数可以被 5 整除。
  • 5 出现的次数可以被 3 整除。

与此同时,“野兽”的毁灭反击速度非常快。你能拯救“野兽”,并在夏洛克之前找到钥匙吗?

输入格式 第一行将包含一个整数 T,即测试用例的数量。接下来是T行,每行包含一个整数N,即数字中的位数

输出格式 具有 N 位数的最大体面数。如果不存在这样的数字,告诉 Sherlock 他错了并打印 '-1'

约束 1

示例输入

4
1
3
5
11

样本输出

-1
555
33333
55555533333

解释 对于 N=1,没有这样的数字。

对于 N=3,555 是唯一可能的数字。

对于 N=5,33333 是唯一可能的数字。

对于N=11, 55555533333 且所有数字的排列都是有效数字,其中给定的数字是最大的。

回答

for _ in range(int(input())):
    n = int(input())
    c = 5*(2*n%3)
    if c > n:
        print(-1)
    else:
        print('5' * (n-c) + '3'*c)

问题

有人可以解释其背后的原因吗?具体来说,“c”变量的赋值是做什么的?

来源:https://www.hackerrank.com/challenges/sherlock-and-the-beast

【问题讨论】:

  • 好吧,首先,2*n%3 将是 0 如果n 可以被 3 整除,2 如果它是 n-1 可以被 3 整除,1 如果@987654331 @ 可以被 3 整除。因此,在这三种情况下,c 将是 0105。 (如果还不清楚,请打印出[5*(2*n%3) for n in range(20)]。)注意c 有什么用处——你有n-c 5 和c 3。这足以弄清楚吗?

标签: python algorithm python-3.x


【解决方案1】:

数学解:

令 a = '5's 的 len,b = '3's 的 len。所以

a + b = N

我们知道3整除a,5整除b,所以设a = 3n, b = 5m

3n+5m = N

这是一个丢番图方程 (http://en.wikipedia.org/wiki/Diophantine_equation),其中一个解是 (n0, m0) = (2N, -N),并且是通解

(n,m) = (5k+2N, 3K-N), k any integer

现在的问题是最小化 3k-N 的数量(因为你想要更多的 '5's),所以 3k-N > 0。 这与找到 3k 是 3 FROM N 的下一个倍数的 k 相同。

例如,如果 N = 10 或 11,我们正在寻找 3k = 12,或 k = 4。

3k-N 因此是 N 与下一个 3 的倍数之间的距离。解决方案的作者声称 3k-N = 2N%3 ,您通过穷举证明这一点,评估 N%3 = 0、1 和 2。为了记录,表达式 '2N%3' 中的 '2' 不是唯一的,它适用于序列 2、5、8、11... 中的任意数字,以及为什么作者选择了这个特定的表达方式,我不能说。

你也可以想一想这个意义上的 N%3 是如何接近 N 与 3 的下一个 LOWER 倍数的距离。

【讨论】:

  • 不应该是(n,m) = (2N + 5k, -N -3K), k any integer吗?因为对于wikipeida页面上写的内容:if (x, y) is a solution, then the other solutions have the form (x + kv, y - ku), where k is an arbitrary integer, and u and v are the quotients of a and b (respectively) by the greatest common divisor of a and b.所以x=2N, y=-N, v=5, u=3你假设u=-3,为什么?谢谢。
【解决方案2】:

好的,思路是这样的。

  1. 一旦你计算出你想要多少个5s 和多少个3s,你应该预先加载5s。排序对数字是否合适没有任何影响;但如果5s 在前面会更大。
  2. 您想要的3s 的数量应该是满足约束条件的最小数量,因为这样您将拥有更多5s,从而获得更大的数量。
  3. 3s 的数量必须能被 5 整除。这意味着任何点都不会超过 10 个3s:您应该只考虑 0、5 或 10 个3s。这是因为您想要使剩余位数可被 3 整除的最小数字来满足其他约束。如果有 15 个3s 有效,那么有 0 个3s 也有效;如果 20 个有效,那么 5 个也有效;如果 25 有效,那么 10 也有效。一般而言,从 3s 的数量中减去 15 将使两个约束仍然满足,如果它们之前是这样。
  4. 因此,5s 的数量必须是 n-0n-5n-10,我们想要一个能被 3 整除的数字。计算 c = 5*(2*n%3) 将得到 0 @987654338 @s 和 n 5s 如果 n 已经被 3 整除;和 10 3s 和因此 n-10 5s 如果 n 大于 3 的倍数,在这种情况下 n-10 仍然可以被 3 整除;等等。
  5. 唯一需要测试的是c3s和n-c5s的计算是否满足n-c应该是非负的隐含约束。如果它是否定的,则没有解决方案;如果它是非负数,那么这是一个有效的解决方案,并且预先加载 5s 将为您提供最大的此类解决方案。

这是一类相当广泛的“编程”问题之一,其中测试并不是真的看你是否可以敲出一些完成这项工作的代码,而是看你是否可以在逻辑上将问题简化为重点它很简单,可以非常有效地解决。

【讨论】:

    【解决方案3】:

    我认为数学有点帮助,我阅读了它的不同部分和历史。我的解决方案第一次通过了所有 15 项测试,所以虽然我没有使用数学,但我对此的看法可能会对您有所帮助。我处理了 10 个或更少的边缘案例,我只是硬编码。任何高于 10 的东西我都除以 3 得到最多的“555”。当然,除以 3 时,余数只能是 0、1 或 2。零当然意味着只需写入 555,但要多次。一种方法是从 555 中减去 3 个,以恢复 10 个空位,用于 10 个三分球。两个意味着减去 555 中的 1 个,从而为 33333 留下 5 个插槽。

    余数为 3 个 if。 10个ifs用于边缘情况。 1 如果用于约束。 1 为。

    【讨论】:

      【解决方案4】:
      x = int(raw_input())
      while x!= 0 :
          y=int(raw_input())
          z=y
          while(z%3!=0):
              z-=5
          if(z<0):
              print '-1'
          else:
              print z*'5'+(y-z)*'3'
          x = x-1
      

      如果数字(比如 66317)不能被 3 整除,它将留下 0,1 或 2 的模数。如果我将数字减少 5,我基本上是使其成为 3 的倍数,并且剩余当我从数字中减去它时,数字将是 5 的倍数。

      模 0 意味着数除模 1 意味着 5 需要减去两次。模 2 意味着 5 需要减去一次。

      【讨论】:

        猜你喜欢
        • 2021-05-25
        • 2012-02-19
        • 1970-01-01
        • 1970-01-01
        • 2022-11-09
        • 1970-01-01
        • 2020-07-29
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多