C, 150 140 135 bytes
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));}
Esta es la versión para sistemas ASCII; reemplace la cadena 33436con 11214un sistema EBCDIC, o con\1\1\2\1\4 un programa portátil.
Las soluciones C están un poco obstaculizadas por el requisito de proporcionar un programa completo; sin embargo, esto responde la pregunta completamente.
Pruébelo en línea (requiere Javascript):
Explicación
Se basa en el algoritmo descrito en el dígito menos nulo menos significativo de n! , volteamos para que recurramos para encontrar la potencia más alta de cinco, y hagamos el cálculo al salir. Las tablas de constantes eran demasiado grandes, así que las reduje al encontrar una relación entre el residuo anterior r, el dígito actual dy la profundidad de recursión 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
Para r>0, esto se resuelve a veces constantes rveces 2^dk(mod 5); las constantes están a[]abajo (en el código de golf). También observamos que (2^4)%5es 1, por lo que podemos reducir el exponente para evitar desbordar el rango de 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 */
}
Pruebas:
$ for i in 100 1000 10000 100000; do echo $i: `./694 $i`; done
100: 4
1000: 2
10000: 8
100000: 6
1000000: 4
El rendimiento también es respetable. Aquí hay una entrada máxima para un sistema con 32 bits int:
$ time ./694 2147483647
8
real 0m0.001s
user 0m0.000s
sys 0m0.000s
También obtuve los mismos tiempos con un máximo de 64 bits int.