被1000003整除?容易,只需将最后一位乘以300001然后加!


16

给定一个P大于的质数10,您的程序或函数必须弄清楚其除数规则x,定义为具有最小绝对值的整数,当将其与质数的最后一位相乘并加到其余的原始数时,该整数将产生原始质数的倍数主要。

给定输入31,最后一个数字为1,其余数字为3。因此,您的程序必须找到x具有最小绝对值的整数,该整数应1*x + 3是的倍数31。在这种情况下,x=-3可以正常工作,因此程序或函数将返回-3

给定输入1000003,最后一个数字为3,其余数字为100000。这样您的程序就会找到,x=300001因为3*300001+100000 = 1000003它是的倍数1000003

数学背景

的值x可以用作除数检验。如果一个数字可N被整除P,则将x的最后一位数字N与的余数相加N将得到Pif和only N的可被P第一个整数整除的倍数。

因为P=11,我们得到x=-1,它等于以下公知的除数规则11:一个数字可通过11交替改变其数字的位数来除以11

规则

  • 输出可以采用任何清楚地编码输出的符号和值的形式。
  • 输入素数将在10到2 ^ 30之间。
  • 如果输入不是素数或不在范围内,则无需处理。
  • 如果x-x均为有效输出,则不需要处理(不应发生)。
  • 允许使用蛮力,但希望有更多创造性的解决方案。
  • 这是,因此每种语言中最短的代码胜出!不要让打高尔夫球的语言的答案妨碍您发布其他语言的信息。

测试用例

Input   Output
11  -1
13  4
17  -5
19  2
23  7
29  3
31  -3
37  -11
41  -4
43  13
47  -14
53  16
59  6
61  -6
67  -20
71  -7
73  22
79  8
83  25
89  9
97  -29
101 -10
103 31
107 -32
109 11
113 34
127 -38
131 -13
1000003 300001
2000003 600001
2999999 300000
9999991 -999999

3
一个有用的简化:我们正在寻找x绝对值最小10*x-1的输入可被其整除的绝对值。
xnor

任何人都可以提供这样的提示,(3 / (n % 5 * 2 - 5) * n + 1) / 10(n % 5 * 2 - 5^2) * n / 10 + 1能够找到类似这样的最小绝对值吗?我的第一个直觉是使用通过Euclid算法计算出的最大公因数来计算最小公倍数。
大卫·佛斯特

1
@DavidFoerster给定一个数字,您可以删除最后一个数字,将其乘以一个数字x,加上后,仍然得到一个可被整除的数字n。如果我们然后将新数字乘以10并减去原始数字,则它仍可被整除n。然后,xnor的评论来自一些代数。下一步是重新排列公式,使公式xn:x = (k*n+1)/10。我们希望最小的绝对x因此,因此,我们希望绝对值最小k,而这必须是哪一个-3-113(视n的最后一位数字),使部门精确。
尼尔

Answers:


14

JavaScript(ES6),32 25 23字节

f=
n=>(3/(n%5*2-5)*n+1)/10
<input type=number min=1 oninput=o.textContent=this.value%5*(this.value%2)?f(this.value):``><pre id=o>

3/(n%5*2-5)9/n(mod -10)如果我可以使用平衡模除法,将被写入。编辑:感谢@EgorSkriptunoff保存了2个字节


3
您可以通过更换节省2个字节n=>((n%10*2%14-3)*n+1)/10n=>(3/(n%5*2-5)*n+1)/10
叶戈尔Skriptunoff


@KevinCruijssen可能也是Java 8的一个差点而已。
尼尔

@尼尔你是对的。我通常会发布Java答案,因此当我看到您的答案时,我已经在xnor上工作。不管用哪种方式发布它,都是无聊的端口。
凯文·克鲁伊森

8

Python 2,27个字节

lambda n:(n%5*2-5^2)*n/10+1

在线尝试!

操作从左到右完成: (((n%5)*2)-5)^2

我用算术蛮力搜索找出n%5*2-5^2要执行的表达式{1:-1,3:3,2:-3,4:1}[k],将残差mod 5的负逆取到范围内[-2..2]


算术强力逼迫者在某处公开可用吗?
林恩

是找到的唯一表达式,还是只是打印给定长度的第一个表达式?(3/(n%5*2-5)长度与(n%5*2-5^2).. 相同)
Neil

@Lynn不,我有空的时候可能会清理并张贴它。
xnor

1
@Neil仅找到和的等效项n%5*2-6^3。我只查找了不带括号的表达式的长度,虽然长了3/(n%5*2-5)两个字符,但是由于优先级而节省了外部括号。搜索此长度的表达式需要一段时间。该用例确实提出了一个选择,即仅通过具有最高优先级的最外层操作来查找可在给定上下文中使用的表达式。
xnor

6

果冻10 8字节

,N⁵æiAÞḢ

在线尝试!

说明

,N       Get [Input, -Input].
⁵æi      Modular inverse of 10 mod each of [Input, -Input].
AÞ       Sort by absolute value.
Ḣ        First.

+1我从未见过有寄存器的Jelly提交实际上节省了字节
Xcoder先生17年

@ Mr.Xcoder是因为我打高尔夫球不好。
jimmy23013




5

杰普特16 9字节

@xnor的观察节省了太多的字节

_*AÉ vU}c

在线测试!较大的输入可能需要几秒钟。

说明

_  *AÉ  vU}c    Implicit: U = input integer
Z{Z*A-1 vU}c    Ungolfed
Z{        }c    Loop through each integer Z in [0, -1, 1, -2, ...] and yield the first where
  Z*A             Z times 10
     -1           minus 1
        vU        is divisible by the input.
                Implicit: output result of last expression




1

Python 2中44 43个字节

(删除的44仍然是44。)感谢Fireflame241节省了一个字节!

P=input();i=P/3
while i*10%P-1:i-=1
print i

在线尝试!

之间恰好有一个数字,0并且P-1是的倒数10。但是,如果该逆u恰好大于P/2,则(u-P)它也是一个逆,并且绝对值小于u。事实证明,我们实际上是x-P/2和之间寻找唯一数字,P/2这是10

上面的代码正是这样做的,从(的底部)开始P/2,然后逐步向下直到达到逆。-P/2只要P大于的素数,就必须发生大于的数10。更确切地说,它将仅在以下情况下终止P与互素时10

编辑:实际上,事实证明x保证在-P/3和之间P/3,因此当前版本P/3从此处开始并从此处逐步降低。有关此说明,请参见标记为“ 改进的范围”的部分。

数学解释

对我而言,立即进行除数测试的原因并不十分明显。如果其他人想知道的话,这是一个解释。

P一个大于10它的最后一个数字为的质数b。从而

P = 10a + b

a > 00 <= b < 10。其实b要么是137,或者9,因为黄金大于10在这些数字一个必须结束。

现在假设bx + a = 0 (mod P)。然后

a = -bx (mod P)

10a + b = 10(-bx) + b (mod P)

0 = 10(-bx) + b (mod P)

0 = b(1 - 10x) (mod P)

由于P是质数,所以整数mod P整数域。因此,要么b = 0 (mod P),或1 - 10x = 0 (mod P)

我们知道0 <= b < 10 < P,如果b = 0 (mod P)b = 0。但是,我们说b要么137,或9,所以这是不可能的。因此1 - 10x = 0 (mod P),如此10x = 1 (mod P)。换句话说,x10,模的倒数P

现在假设N是一个非负整数,其最后一位是d,因此N = 10c + d. 我们有一系列等效语句:

10c + d = 0 (mod P)

<==> 10xc + dx = 0 (mod P)

<==> c + dx = 0 (mod P)

QED。

有用吗?

我还想知道,除数测试(给定N = 10c + d,替换Ndx + c)在实践中是否真的会富有成效。还是至少可以可靠地用N小于N(绝对值)的数字代替?

假设N = 10c + d在哪里c >= 00 <= d < 10。因此10c = N - d <= N。通过三角形不等式,

|c + dx| <= |c| + |dx| = c + d|x| <= N/10 + d|x|

< N/10 + 10|x| <= N/10 + 10P/2 = N/10 + 5P

因此,如果5P <= 9N/10,然后|c + dx| < N

特别是如果N >= 6P,则|c + dx| < N。因此,鉴于P我们首先计算2P3P,... 6P,伴随着x。然后给出N,我们反复运行试验整除直到我们达到一个数量小于或等于6P,并检查结果是否是任意的数字0P2P,..., 6P

(当然,每当达到负数时,我们都用它的绝对值代替它,这是很好的,因为q可以被Pif和only is整除(-q)。)

改良绑定

我注意到这|x|/P似乎从未接近过1/2。实际上,它似乎总是小于1/3...或经过仔细检查,它总是非常接近1/103/10。最大的以往任何时候都得到了似乎是4/13(发生时P=13x=4)。为什么会这样呢?

u一个整数,并假设10u = kP + 1对于某个整数ku10modulo 的逆P。然后我们也知道k相对于质数10,因为k(-P)等效于110

现在,我们知道10模的反数P都相差了的倍数P,因此我们可以取整数u并随意添加或减去的倍数,P结果仍然始终是10模的反数P。假设我们选择减去P来自u:我们得到

10(u - P) = 10u - 10P = kP + 1 - 10P

10(u - P) = (k - 10)P + 1

换句话说,减少(分别增加)uP对应于减小(增加)k通过10。我们希望加/减的倍数Pu直到左侧的绝对值最小化; 但是当右侧最小化时,左侧恰好被最小化,因此我们要添加/减去10k直到绝对值最小化右侧。

但我们知道,何时会发生k之间-55,因此(因为k是相对素10)。这意味着k要么是-3-11,或3。(这是OP下@Neil的评论内容。谢谢,尼尔!

因此,当|u|被最小化(即u=x),我们将有x/P = u/P = k/10 + 1/(10P),那里k要么是-3-11,或3。因此|x|/P <= 3/10 + 1/(10P)。等效地,|x| <= (3P + 1)/10

此外,这种不平等是严格的P=11,因为P=11我们有x=-1k=-1。最小的P为这等式成立的P=13(这里x=4k=3)。

因此,最大的|x|/P有史以来得到的是3/10 + 1/(10*13),因为P=13是我们有第一任k=3,以及那些之中k=3,在1/(10P)当期限是最大P最小(即,P=13)。因此,对于所有人来说P,我们也有|x|/P <= 3/10 + 1/130 = 4/13 < 1/3。这解释了为什么在上面的代码中我们可以在i = P/3而不是从处开始进行初始化P/2

此外,现在可以改善上面“ 有用性”部分中的范围。

引理:让N = 10c + d地方c > 00 <= d <= 9。然后c + d|x| < N/10 + 9(3P + 1)/10。(请注意严格的不等式。)

引理证明:根据情况。案例I:d = 0N = 10c。然后c + d|x| = c = N/10 < N/10 + 9(3P + 1)/10

情况二:0 < d <= 9。然后10c = N - d < N,这样c < N/10。因此c + d|x| < N/10 + d|x| <= N/10 + 9|x| <= N/10 + 9(3P + 1)/10。QED。

因此,如果N > 3P(和N = 10c + d以前一样),则

3P + 1 <= N

9(3P + 1)/10 <= 9N/10

N/10 + 9(3P + 1)/10 <= N

c + d|x| < N/10 + 9(3P + 1)/10 <= N

所以,如果N > 3P那么c + d|x| < N

因此,我们只需要找到P2P并且3P,随着x。鉴于N > 0,同时N > 3P,我们替换N|c + dx|,这降低N。最终我们会得到N <= 3P; 在这一点上,我们停下来检查是否N等于任何数字的0P2P,或3P

我们不能做得比3P一般更好。例如,假设P = 13N = 39,所以x = 4。然后用不变Ndx + c = 9(4) + 3树叶代替N


很好的解释!您可以通过移动-1括号来节省一个字节: 43个字节
fireflame241

@ fireflame241非常感谢!我可以说我把它留在了44岁,所以我可以删掉它(尽管这是一个谎言)。
mathmandan

1

空格,92字节

请注意,该语言的语法包含空白,因此每个空白字符都在此处以S,T或L作为前缀(分别对应于空格,制表符和换行符)。可以删除这些文件而不会丢失功能,但是为了正确显示它们,此处将其包括在内。

S S S L
T   L
T   T   S S S L
T   T   T   S L
S S S S T   T   L
T   S S L
S L
T   S S S T S T L
T   S T T   S L
S T S S S S S S T   S T L
T   S S T   T   S T S S S S T   L
T   S S S S S S T   S T S L
T   S T S T L
S T L
L
L
.

在线尝试!


1

Japt,14个字节

尼尔的解决方案启发。

Ì*2%E-3 *UÄ /A

在线测试!

说明:

  Ì  *2%E-3 *UÄ  /A
((UgJ*2%E-3)*U+1)/A
  U                  // Implicit U = Input
   gJ                // Get the char at index -1 (last char)
     *2              // Multiply by 2
       %E            // Mod 14
         -3          // Minus 3
            *U+1     // Multiply by U+1
                 /A  // Divided by 10 


0

Excel,27个字节

=0.3/(MOD(A1,5)*2-5)*A1+0.1

可以输入为

=.3/(MOD(A1,5)*2-5)*A1+.1

25个字节,但Excel自动更新。


实际上,我认为您可以要求输入需要输入的字节数(但是我懒于检查meta)。
尼尔
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.