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));}
Ini adalah versi untuk sistem ASCII; ganti string 33436dengan 11214untuk sistem EBCDIC, atau dengan \1\1\2\1\4untuk program portabel.
Solusi C agak terhambat oleh persyaratan untuk menyediakan program lengkap; Namun, ini menjawab pertanyaan sepenuhnya.
Cobalah online (memerlukan Javascript):
Penjelasan
Ini didasarkan pada algoritma yang digariskan dalam Least Significant Non-Zero Digit of n! , berbalik sehingga kita kembali untuk menemukan kekuatan tertinggi lima, dan melakukan perhitungan di jalan keluar. Tabel konstanta terlalu besar, jadi saya menguranginya dengan menemukan hubungan antara residu sebelumnya r, digit saat ini ddan kedalaman rekursi 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
Sebab r>0, ini menyelesaikan ke kali rkali konstan 2^dk(mod 5); konstanta ada di a[]bawah (sebaris dalam kode golf). Kami juga mengamati bahwa itu (2^4)%5adalah 1, sehingga kami dapat mengurangi eksponen untuk menghindari meluapnya kisaran 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 */
}
Tes:
$ for i in 100 1000 10000 100000; do echo $i: `./694 $i`; done
100: 4
1000: 2
10000: 8
100000: 6
1000000: 4
Performanya juga terhormat. Berikut input maksimum untuk sistem dengan 32-bit int:
$ time ./694 2147483647
8
real 0m0.001s
user 0m0.000s
sys 0m0.000s
Saya mendapat timing yang sama dengan 64-bit maksimal intjuga.