두 자리 숫자 *3의 첫번째 자리를 여러가지로 바꿨을 때 가능한 아홉 가지의 결과 중에서 13, 23, 43, 53, 73, 83의 여섯 개는 소수입니다.
56**3 의 3번째와 4번째 자리를 동일한 숫자로 바꿔서 만들어지는 10개의 다섯자리 숫자 중에서는 아래에서 보듯이 7개가 소수가 되며, 이것은 이런 식으로 7개의 소수가 만들어지는 첫번째 경우입니다. 이 소수 집단의 첫번째 수인 56003은 이런 성질을 갖는 가장 작은 소수입니다.
56003, 56113, 56333, 56443, 56663, 56773, 56993
위의 예처럼 원래의 일부를 동일한 숫자로 치환했을 때 8개의 소수 집단이 만들어지는 경우를 찾고, 그 집단에 속한 가장 작은 소수를 구하세요.
치환하는 자리는 인접하지 않아도 되고, 가장 앞부분을 치환하는 경우 거기에 0은 올 수 없습니다.
Click 56**3 의 3번째와 4번째 자리를 동일한 숫자로 바꿔서 만들어지는 10개의 다섯자리 숫자 중에서는 아래에서 보듯이 7개가 소수가 되며, 이것은 이런 식으로 7개의 소수가 만들어지는 첫번째 경우입니다. 이 소수 집단의 첫번째 수인 56003은 이런 성질을 갖는 가장 작은 소수입니다.
56003, 56113, 56333, 56443, 56663, 56773, 56993
위의 예처럼 원래의 일부를 동일한 숫자로 치환했을 때 8개의 소수 집단이 만들어지는 경우를 찾고, 그 집단에 속한 가장 작은 소수를 구하세요.
치환하는 자리는 인접하지 않아도 되고, 가장 앞부분을 치환하는 경우 거기에 0은 올 수 없습니다.
http://nianelo4.blog.me/ 블로그의 동일 문제 풀이에 대해 참고.
1. 마지막 자리에 짝수나 5가 올 경우 2의 배수 혹은 5의 배수이므로 마지막 자리에 올 수 있는 수는 1,3,7,9가 전부.
2. 반복되는 수의 갯수는 3의 배수개일 때만 가능하다.
3의 배수 판단법으로 각 자리의 수를 모두 더했을 때 3의 배수가 되는 수를 찾는 방법을 이용.
반복 되는 수가 3의 배수가 아닐때 각 자릿수를 더한 값은 3번의 한번 3의 배수가 된다.
즉 반복되는 수가 3의 배수이고, 그 외의 자릿수들의 합이 3의 배수가 아닐때 만 8개 이상의 값이 나올 수 있다.
알고리즘은 해당 블로그와 다르네요.2. 반복되는 수의 갯수는 3의 배수개일 때만 가능하다.
3의 배수 판단법으로 각 자리의 수를 모두 더했을 때 3의 배수가 되는 수를 찾는 방법을 이용.
반복 되는 수가 3의 배수가 아닐때 각 자릿수를 더한 값은 3번의 한번 3의 배수가 된다.
즉 반복되는 수가 3의 배수이고, 그 외의 자릿수들의 합이 3의 배수가 아닐때 만 8개 이상의 값이 나올 수 있다.
일단 각 자릿수마다 사용하는 패턴이 다르므로 자릿수 증가시마다 패턴을 새로 구합니다.
각 패턴과 i값에 대해 고정 값 n을 만듭니다.
고정값 n에 패턴 * k 를 더해가며 만들어지는 수에 대해 소수인지를 판단하고 최종적으로 소수의 수를 구합니다.
가장 작은 값을 구하는 것이므로 min값이 나온 자릿수보다 자릿수 증가가 일어나기 전까지 연산을 해봅니다.
<script language="Javascript" type="text/javascript">
/* 소수 판단. */
function isPrime(n){
if(n < 2) return false;
else if(n < 4) return true;
else if(n%2 == 0 || n%3 == 0) return false;
for(var i=5; i*i<=n; i+=6)
if(n%i == 0 || n%(i+2) == 0)
return false;
return true;
}
//t와 f의 수의 따라 가능한 패턴을 얻는다.
function get051Patterns(t,f,patterns,tn,fn){
if(t==tn && f==fn)
return [patterns];
var r = [];
if(fn < f)
r = get051Patterns(t, f, patterns*10, tn, fn+1);
if(tn < t){
var temp = get051Patterns(t, f, patterns*10+1, tn+1, fn);
for(var i in temp)
r[r.length] = temp[i];
}
return r;
}
function p051(){
var pn = 3, goal = 8; //기본 변수 설정.
var digit = 0, ten = 1, patterns, min = Number.MAX_VALUE, minDig = 100;
for(var i=1; ; i+=(i%10==3)?4:2){
//자릿수 증가시 새로운 패턴을 얻음.
if(i >= ten){
if(minDig == digit)
break;
patterns = get051Patterns(pn, digit++, 0, 0, 0);
ten *= 10;
}
for(var j in patterns){
//패턴과 i값을 이용해 고정 값 n을 얻음.
var cnt = 0;
var pattern = patterns[j] * 10;
var n = i;
for(var k=1; k < pattern; k*=10)
if(~~(pattern/k)%10 == 1)
n = (parseInt(n/k))*k*10 + n%k;
//고정값에 패턴값을 더해가며 소수를 찾음.
var t = Number.MAX_VALUE;
for(var k=(pattern < ten * Math.pow(10, pn-1))?0:1; goal<11-k+cnt; k++){
if(isPrime(n + pattern*k)){
if(n+pattern*k < t){
t = n+pattern*k;
if(t > min)
break;
}
cnt ++;
}
}
//소수의 수를 파악하여 결과값을 구함.
if(cnt >= goal){
if(min>t){
min = t;
minDig = digit;
}
}
}
}
alert(min);
}
</script>
탐색 시간 0.02초 정도.
댓글 없음:
댓글 쓰기