C, 150 (140) 135 바이트
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));}
이것은 ASCII 시스템의 버전입니다. 문자열 33436
을 11214
EBCDIC 시스템 또는 \1\1\2\1\4
휴대용 프로그램으로 바꿉니다.
C 솔루션은 전체 프로그램을 제공해야한다는 요구 사항에 약간 방해가됩니다. 그러나 이것은 질문에 완전히 대답합니다.
온라인으로 사용해보십시오 (Javascript 필요) :
설명
그것은 n의 최소 중요하지 않은 자릿수에 요약 된 알고리즘을 기반으로합니다 ! , 우리는 5의 최대 거듭 제곱을 찾기 위해 되풀이되어 나갈 때 계산을 수행합니다. 상수 테이블이 너무 커서 이전 잔차 r
, 현재 숫자 d
및 재귀 깊이 사이의 관계를 찾아서 축소했습니다 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
의 경우 r>0
, 이는 일정한 시간 r
시간 2^dk
(mod 5)으로 해결됩니다 . 상수는 a[]
아래 에 있습니다 (골프 코드에 인라인되어 있음). 또한이 값 (2^4)%5
이 1 임을 관찰 하여의 범위가 넘치지 않도록 지수를 줄일 수 있습니다 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 */
}
테스트 :
$ for i in 100 1000 10000 100000; do echo $i: `./694 $i`; done
100: 4
1000: 2
10000: 8
100000: 6
1000000: 4
성능도 훌륭합니다. 다음은 32 비트 시스템의 최대 입력입니다 int
.
$ time ./694 2147483647
8
real 0m0.001s
user 0m0.000s
sys 0m0.000s
최대 64 비트 int
에서도 동일한 타이밍을 얻었 습니다.