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));}
Questa è la versione per sistemi ASCII; sostituire la stringa 33436con11214 per un sistema EBCDIC o con \1\1\2\1\4per un programma portatile.
Le soluzioni C sono un po 'ostacolate dall'obbligo di fornire un programma completo; tuttavia, questo risponde completamente alla domanda.
Provalo online (richiede Javascript):
Spiegazione
Si basa sull'algoritmo descritto nella cifra non zero meno significativa di n! , si voltò in modo da ricorrere per trovare la massima potenza di cinque e fare il calcolo all'uscita. Le tabelle delle costanti erano troppo grandi, quindi le ho ridotte trovando una relazione tra il residuo precedente r, la cifra corrente de la profondità di ricorsione 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
Per r>0, questo viene risolto in un costante volte rvolte 2^dk(mod 5); le costanti sono in a[]basso (indicate nel codice golf). Osserviamo anche che (2^4)%5è 1, quindi possiamo ridurre l'esponente per evitare di traboccare il range di 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 */
}
test:
$ for i in 100 1000 10000 100000; do echo $i: `./694 $i`; done
100: 4
1000: 2
10000: 8
100000: 6
1000000: 4
Anche le prestazioni sono rispettabili. Ecco un input massimo per un sistema a 32 bit int:
$ time ./694 2147483647
8
real 0m0.001s
user 0m0.000s
sys 0m0.000s
Ho avuto gli stessi tempi anche con un massimo di 64 bit int.