基数中阶乘的最后一个非零数字


22

您应该编写一个程序或函数,该程序或函数给出三个正整数n b k作为输入输出,或者返回k的基本b表示形式中的尾随零之前的最后一位数字n!

n=7 b=5 k=4
factorial(n) is 5040
5040 is 130130 in base 5
the last 4 digits of 130130 before the trailing zeros are 3013
the output is 3013

输入项

  • 3个正整数n b k,其中2 <= b <= 10
  • 输入整数的顺序可以任意选择。

输出量

  • 返回或输出为整数或整数列表的数字列表。
  • 前导零是可选的。
  • 您的解决方案必须在一分钟之内在我的计算机上解决任何示例测试用例(我将仅测试关闭的用例。我的PC低于平均水平。)。

例子

添加了新测试以检查提交的正确性。(它们不属于1分钟内运行时规则的一部分。)

输入=>输出(可以选择省略前导零)

3 10 1  =>  6

7 5 4  =>  3013

3 2 3  =>  11

6 2 10  =>  101101

9 9 6  =>  6127

7 10 4  =>  504

758 9 19  =>  6645002302217537863

158596 8 20  =>  37212476700442254614

359221 2 40  =>  1101111111001100010101100000110001110001

New tests:
----------

9 6 3  =>  144

10 6 3  =>  544

这是代码高尔夫球,因此最短的条目将获胜。


1
如果我们不了解任何细节,则很难在计算机上等待不到一分钟
丹尼斯

1
7 5 3输出“ 013”还是“ 13”?
Claudiu

1
@Claudiu基于7 10 4测试用例,我会说13
Maltysen 2015年

2
@Claudiu“前导零是可选的。” 所以两个版本都是正确的。
randomra 2015年

1
我们必须接受或的任何正整数吗?还是可以将它们限制为语言的整数类型的范围?nk
Toby Speight

Answers:


1

Dyalog APL,23个字节

⌽k↑⌽{⍵↓⍨-⊥⍨0=⍵}b⊥⍣¯1⊢!n

只要阶乘不超过内部表示限制,此程序就可以工作。在Dyalog APL中,可以将限制提高⎕FR←1287

假设已经设置了变量n,b和k(例如n b k←7 5 4),但是如果您想提示nbk(按顺序),则用替换三个字符


在我的机器(M540)上,我投入的每个测试用例大约需要11微秒的时间。
亚当

7

Mathematica,57 48个字节

由于@ 2012rcampion节省了9个字节。

IntegerString[#!/#2^#!~IntegerExponent~#2,##2]&

我从来没有真正使用过mathematica,但是您不能交换参数的顺序以使其b首先保存2个字节吗?
FryAmTheEggman

@FryAmTheEggman我是高尔夫社区的新手,正在交换参数顺序“犹太”吗?
2012rcampion 2015年

1
您实际上可以达到47 :(IntegerString[#!#2^-#!~IntegerExponent~#2,##2]&这和您的原件都非常快)
2012rcampion 2015年

询问者写道:“输入整数的顺序可以任意选择。” 在输入下,因此在这种情况下肯定没问题
FryAmTheEggman

@Fry Wow,看来我读得不够仔细。但是,SlotSequence我在评论中使用的技巧仅适用于当前订单,因此您无法再保存任何内容。
2012rcampion 2015年

7

Python,198 192 181个字符

def F(n,b,k):
 p=5820556928/8**b%8;z=0;e=f=x=1
 while n/p**e:z+=n/p**e;e+=1
 z/=1791568/4**b%4;B=b**(z+k)
 while x<=n:f=f*x%B;x+=1
 s='';f/=b**z
 while f:s=str(f%b)+s;f/=b
 return s

它足够快,最大示例约为23秒。而且没有析因内置函数(我正在看着你,Mathematica!)。


[2,3,2,5,3,7,2,3,5][b-2]可能是int('232537235'[b-2])保存3个字节。[1,1,2,1,1,1,3,2,1][b-2]同样。
randomra'5

对于后者,查找表111973>>2*(b-2)&3甚至更短。通过(90946202>>3*(b-2)&7),前者的字节数相同。
Sp3000

nvm看起来像您对高位数的东西是正确的
Sp3000

我相信您可以通过将其作为程序而不是函数来节省一些字节。
FryAmTheEggman,2015年

6

Pyth,26 35字节

M?G%GHg/GHH.N>ju%g*GhHT^T+YslNN1T_Y

这是3个参数(数字,基数和位数)的函数。

示范。

最慢的测试用例(最后一个用例)在我的计算机上需要15秒。


@ Sp3000我添加了一个修复程序,我认为它应该足够了。
isaacg

2

PARI / GP,43个字节

空间交易速度产生了这种简单的算法:

(n,b,k)->digits(n!/b^valuation(n!,b)%b^k,b)

每个测试用例在我的机器上运行都不到一秒钟。


2

Mathematica-48个字节

#!~IntegerDigits~#2/.{l__,0...}:>{l}~PadLeft~#3&

取消高尔夫:

Function[{n, b, k},
  IntegerDigits[n!, b] (* list of the base-b digits in n! *)
  /. {l__, 0...} (* match a sequence of elements l and some number of zeros*)
                 (* lucky for me, __ defaults to match the shortest number *)
     :> PadLeft[List[l], k] (* pad l to be k elements long with zeros on the left *)
                            (* this truncates the list if it is too long*)
]

例:

#!~IntegerDigits~#2/.{l__,0...}:>{l}~PadLeft~#3 &
%[758, 9, 19] // Timing

(* {0.031250, {6, 6, 4, 5, 0, 0, 2, 3, 0, 2, 2, 1, 7, 5, 3, 7, 8, 6, 3}} *)

在大多数情况下,限制因素不是生成数字:

Length@IntegerDigits[359221!, 2] // Timing
(* {0.109375, 6111013} 6.1M digits in 100 ms *)

模式匹配似乎是O(n^2),导致最后两个测试用例远远超过了一分钟的标记。


2

Bash / coreutils / dc,60个字节

dc<<<"1 `seq -f%g* $1`$2op"|sed -r s/0+$//|tail -c$(($3+1))

采用dc从脚本我的答案找到阶乘,在基地输出$2,与sed修剪尾随零和tail选择最后$3的数字。


我必须承认,使用40位base-2测试用例的速度非常慢。我尝试减轻sed的工作量rev以减少回溯,但这dc是吃CPU的问题
Toby Speight

2

Haskell,111 109字节

import Data.Digits
f n b k=digits b$foldl(((unDigits b.reverse.take k.snd.span(<1).digitsRev b).).(*))1[1..n]

用法:f 158596 8 20->[3,7,2,1,2,4,7,6,7,0,0,4,4,2,2,5,4,6,1,4]

f 359221 2 40我4岁的笔记本电脑大约需要8秒钟。

工作原理:将乘法(*)折叠到list中[1..n]。将每个中间结果转换b为数字列表的基数(最低有效位在前),去除前导零,然后取第一位k数字并再次转换为基数10。最后b再次转换为基数,但先转换最高有效数字。


您在我的脑海中有了一个想法,那就是我正在使用matlab对其进行解释,这是一个巧合:D
Abr001am 2015年

1

Python 3,146个字节

import math
i,f=input(),int
n=i.split()
e=math.factorial(f(n[0]))
d=''
while e>0:
 d=str((e%f(n[1])))+d;e=e//f(n[1])
print(d.strip('0')[-f(n[2]):])

我不确定测试用例是否会足够快地运行-较大的用例会非常慢(因为它遍历数字)。

在此处在线尝试(但要小心)。


1

爪哇303 299 296字节

import java.math.*;interface R{static void main(String[]a){BigInteger c=new BigInteger(a[1]),b=c.valueOf(1);for(int i=new Integer(a[0]);i>0;i--){b=b.multiply(b.valueOf(i));while(b.mod(c).equals(b.ZERO))b=b.divide(c);b=b.mod(c.pow(new Integer(a[2])));}System.out.print(b.toString(c.intValue()));}}

在我的计算机上,359221 2 40测试用例的平均时间不到三分之一秒。通过命令行参数获取输入。


1

bc,75个字节

define void f(n,b,k){
obase=b
for(x=1;n;x%=b^k){
x*=n--
while(!x%b)x/=b}
x}

这使用一些GNU扩展来减小代码大小。符合POSIX的等效项重80字节:

define f(n,b,k){
obase=b
for(x=1;n;x%=b^k){
x*=n--
while(x%b==0)x/=b}
return(x)}

为了使运行时间合理,我们会修剪尾随的零(while(!x%b)x/=b)并截断为最终k数字(x%=b^k计算阶乘(for(x=1;n;)x*=n--)时()。

测试程序:

f(3, 10, 1)
f(7, 5, 4)
f(3, 2, 3)
f(6, 2, 10)
f(9, 9, 6)
f(7, 10, 4)
f(758, 9, 19)
f(158596, 8, 20)
f(359221, 2, 40)
f(9, 6, 3)
f(10, 6, 3)
quit

在我的2006年老式工作站上,完整测试套件的运行时间约为4¼秒。


这是我有史以来的第一个bc程序(无论是否高尔夫),因此特别欢迎收到任何提示……
Toby Speight,

0

PHP,80字节

function f($a,$b,$c){echo substr(rtrim(gmp_strval(gmp_fact($a),$b),"0"),-1*$c);}

用作 f(359221,2,40)最后一个测试用例。对于所有测试用例,运行都非常平稳。

在这里尝试!

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.