C, 150 140 135 byte
r,d;f(k,x){r=x<5?3:f(k+1,x/5);return(d=x%5)?r*"33436"[d]*(1<<d*k%4)%5:r;}main(int c,char**v){c=atoi(*++v);printf("%d",c<2?1:2*f(0,c));}
Đây là phiên bản cho các hệ thống ASCII; thay thế chuỗi 33436
bằng 11214
cho một hệ thống EBCDIC hoặc bằng \1\1\2\1\4
một chương trình di động.
Các giải pháp C hơi bị cản trở bởi yêu cầu cung cấp một chương trình đầy đủ; tuy nhiên, điều này không trả lời đầy đủ câu hỏi.
Dùng thử trực tuyến (yêu cầu Javascript):
Giải trình
Nó dựa trên thuật toán được nêu trong Số ít nhất không chữ số của n! , quay lại để chúng tôi tái diễn để tìm ra sức mạnh cao nhất trong năm và thực hiện phép tính trên đường ra. Các bảng hằng số quá lớn, vì vậy tôi đã giảm chúng bằng cách tìm mối quan hệ giữa phần dư trước đó r
, chữ số hiện tại d
và độ sâu đệ quy k
:
0 1 2 3 4 =d
0 0 3×2^k 1×2^2k 3×2^3k 2
1 1 1×2^k 2×2^2k 1×2^3k 4
r 2 2 2×2^k 4×2^2k 2×2^3k 3
3 3 3×2^k 3×2^2k 3×2^3k 2
4 4 4×2^k 4×2^2k 4×2^3k 1
Đối với r>0
, điều này giải quyết đến một lần không đổi r
lần 2^dk
(mod 5); các hằng số nằm ở a[]
bên dưới (được đánh dấu trong mã đánh gôn). Chúng tôi cũng quan sát đó (2^4)%5
là 1, vì vậy chúng tôi có thể giảm số mũ để tránh tràn phạm vi int
.
const int a[] = { 1, 1, 2, 1, 4 };
int f(int k, int x){
int r = x<5 ? 3 : f(k+1,x/5); /* residue - from recursing to higher-order quinary digits */
int d = x%5;
if (!d)
return r;
return r * a[d] * (1<<d*k%4) % 5;
}
int main(int c, char **v)
{
c = atoi(*++v);
printf("%d",
c<2
? 1 /* special-case 0 & 1 */
: 2*f(0,c)); /* otherwise, it's 2 times r */
}
Các xét nghiệm:
$ for i in 100 1000 10000 100000; do echo $i: `./694 $i`; done
100: 4
1000: 2
10000: 8
100000: 6
1000000: 4
Hiệu suất là đáng kính, quá. Đây là một đầu vào tối đa cho một hệ thống có 32 bit int
:
$ time ./694 2147483647
8
real 0m0.001s
user 0m0.000s
sys 0m0.000s
Tôi cũng có cùng thời gian với 64 bit tối đa int
.