找到“体面”数字算法推理?

时间:2014-10-27 20:46:12

标签: python algorithm python-3.x

问题

夏洛克·福尔摩斯对他的大敌莫里亚蒂教授感到十分偏执。他所有压制Moriarty的努力都是徒劳的。这些天Sherlock正在研究Watson博士的一个问题。沃森提到中情局最近一直面临着超级计算机怪兽的奇怪问题。

今天下午,Sherlock收到了Moriarty的一张纸条,说他已经感染了The Beast' The Beast'带着病毒。此外,纸币上印有数字N.在做了一些计算之后,Sherlock发现消除病毒的关键是最大的“体面的”#39;数字有N位数。

A'体面'号码有 -

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

与此同时,反对“野兽”的破坏。跑得很快。你可以保存野兽'并在Sherlock之前找到钥匙吗?

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

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

约束 1·; = T< = 20 1·; = N< = 100000

示例输入

4
1
3
5
11

样本输出

-1
555
33333
55555533333

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

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

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

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

答案

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

4 个答案:

答案 0 :(得分:16)

数学解决方案:

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

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'),所以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,1 ...,以及为什么作者选择了这个特殊的表达方式,我不能说。

你也可以考虑N%3在这个意义上是如何接近N的下一个LOWER倍数。

答案 1 :(得分:4)

好的,这个想法是这样的。

  1. 一旦你计算出了多少5和多少3你想要的,你应该预先加载5。这个订单对于数字是否合适没有任何可能性;但如果5位于前面,它会更大。
  2. 您想要的3个数应该是满足约束条件的最小数字,因为那样您会有更多的5 s,从而产生更大的数字。
  3. 3的数量必须可以被5整除。这意味着从来没有任何一个点超过10 3:你应该只考虑0,5或10 { {1}}秒。这是因为您希望保留最小数字,将剩余数字的数量除以3,以满足另一个约束。如果有15 3个有效,那么0 3 s也是如此;如果20个工作,那么5个工作;如果25有效,那么10也是如此。一般来说,从3的数量中减去15会使约束在以前都满意。
  4. 3的数量必须为5n-0n-5,我们希望提供的数字可以被3整除如果n-10已被3整除,则计算c = 5*(2*n%3)将为您提供0 3 s n 5 s;如果n大于3的倍数,那么3n-10 5nn-10,在这种情况下,c仍可被3整除;等等。
  5. 唯一需要测试的是3 n-c5 n-c s的计算是否满足5应该为非的隐式约束负。如果它是否定的则没有解决方案;如果它是非负面的,那么这是一个有效的解决方案,前端加载{{1}}将为您提供最大的解决方案。
  6. 这是一个非常广泛的"编程"问题,测试不是真的要看你是否可以抨击一些能够完成这项工作的代码,而是看看你是否可以在逻辑上将问题减少到可以非常有效地解决的程度

答案 2 :(得分:0)

我认为数学有点帮助,我读了它的不同部分和历史。我的解决方案第一次通过了所有15个测试,所以当我没有使用数学时,我对此的看法可能对你有帮助。我处理了10个甚至更少的边缘情况,我只是硬编码。超过10的任何东西除以3得到最多的“555”。当然,当除以3时,余数只能是0,1或2.零当然意味着只写555多次。一种方法是减去555中的3个以回到10个三分球的10个开放位置。两个方法减去555中的1个,为33333留下5个插槽。

剩余3个ifs。 边缘情况的10个ifs。 1如果是约束。 1为。

答案 3 :(得分:0)

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或2的模数。如果我将数字减少5,我基本上将它变为3的倍数,并且重新生成数字将是5的倍数,因为我从数字中减去它。

模0表示数字divisibile modulo 1意味着5需要减去两次。模2意味着需要减去5次。