소수 3797에는 왼쪽부터 자리수를 하나씩 없애거나 (3797, 797, 97, 7) 오른쪽부터 없애도 (3797, 379, 37, 3) 모두 소수가 되는 성질이 있습니다.
이런 성질을 가진 소수는 단 11개만이 존재합니다. 이것을 모두 찾아서 합을 구하세요.
(참고: 2, 3, 5, 7은 제외합니다)
Click이런 성질을 가진 소수는 단 11개만이 존재합니다. 이것을 모두 찾아서 합을 구하세요.
(참고: 2, 3, 5, 7은 제외합니다)
개인적으로 별로 좋아하는 스타일의 문제는 아니군요. 11개라는 값을 모른다면 무한 탐색을 해야하는 문제고... 무엇보다 무한한 소수중에서 11개라고 딱 정의 내릴 수 있는게 어떻게 가능한지...... 일단 문제를 냈으니 11개는 맞을테지만 그 한계치를 정한 방법이 궁금...
일단 주어진 한계값은 11개밖에 없다는 점 하나군요. 그래서 최대치는 count를 해가며 count값이 11이면 종료하도록 설계.
한계값이 정해져 있다면 에라토스의 체로 모든 소수를 구해 놓은 다음에 그 안에서 판별하는 것도 좋은 방법이겠으나, 한계값이 없으므로 정석대로 brute-force 로 구했습니다.
시작점은 1의 자리가 아니고, 10대의 수 또한 1만 남으면 소수가 아니기 때문에 21부터 시작 짝수는 판단 안해도 되니 2씩 증가.
오른쪽, 왼쪽 부터 지워주는 방법은..
왼쪽부터 지우는 방법은 나누기 10을 해주면 되고..
오른쪽부터 지우는 방법은 생각을 달리해 %10^n씩 해주며 왼쪽부터 쓰는것으로... 역으로 처리하였습니다.
<script language="Javascript" type="text/javascript">
/** 소수 판단.
* @param {Object} n : 판별하고자 하는 수.
* @return {Array} : true, false.
**/
function isPrime(n){
if(n <= 1) return false;
if(n == 2) return true;
else if(n%2 == 0)
return false;
for(var i=3; i*i<=n; i+=2){
if(n%i == 0)
return false;
}
return true;
}
function p037(){
var cnt = 0;
var sum = 0;
for(var i=21; cnt<11; i+=2){
if(isPrime(i)){
var temp1 = i%10;
var temp2 = parseInt(i/10);
var check = true;
for(var j=2; temp1 < i; j++){
if(!isPrime(temp1) || !isPrime(temp2)){
check = false;
break;
}
temp1 = i % Math.pow(10, j);
temp2 = parseInt(temp2/10);
}
if(check){
sum += i;
cnt ++
}
}
}
alert(sum);
}
</script>
그런데 답을 구해놓고 보니 답글란에
첫번째 자리(가장 좌측)에 올 수 있는 수는 {2,3,5,7} 뿐이고...
중간에 들어갈 수 있는 수는 {1,3,7,9} (짝수와 5의 배수를 만들 수 있는 수 제외) 뿐이라는 댓글을 보고 해당 성질을 이용하면 좀 더 효율적으로 구할 수 있을 것 같아서 위에 두 성질에 1의 자리(가장 오른쪽)에는 {3,7}만 가능 하다는 성질을 더해서 새로 구현해 봤습니다.
첫번째 들어 갈 수 있는 수 {2, 3, 5, 7} => 혼자 남았을때 소수가 되는 수.
가운데 들어 갈 수 있는 수 {1, 3, 7, 9} => 1의 자리에 남았을 때 짝수나 5의 배수를 만들지 않는 수.
마지막에 들어 갈 수 있는 수 {3, 7} => 혼자 남았을 때 소수가 되며, 짝수와 5의 배수를 만들 수 없는 수
가운데 들어 갈 수 있는 수 {1, 3, 7, 9} => 1의 자리에 남았을 때 짝수나 5의 배수를 만들지 않는 수.
마지막에 들어 갈 수 있는 수 {3, 7} => 혼자 남았을 때 소수가 되며, 짝수와 5의 배수를 만들 수 없는 수
<script language="Javascript" type="text/javascript">
/** 소수 판단.
* @param {Object} n : 판별하고자 하는 수.
* @return {Array} : true, false.
**/
function isPrime(n){
if(n <= 1) return false;
if(n == 2) return true;
else if(n%2 == 0)
return false;
for(var i=3; i*i<=n; i+=2){
if(n%i == 0)
return false;
}
return true;
}
function p037(){
/* 첫, 중간, 마지막자리에 올 수 있는 값. */
var fn = new Array(2,3,5,7); //첫번째(가장 왼쪽) 올 수 있는 값.
var mn = new Array(1,3,7,9); //중간에 올 수 있는 값.
var ln = new Array(3,7); //마지막(가장 오른쪽) 올 수 있는 값.
/* 각 자리수 탐색 위치 초기 설정. */
var p = new Array();
p[0] = 0;
p[1] = 0;
/* 변수 초기화. */
var cnt = 0;
var sum = 0;
while(cnt<11){
/* n값 구하기. */
var n = fn[p[p.length-1]];
for(var i=p.length-2; i>0; i--){
n = n*10 + mn[p[i]]
}
n = n*10 + ln[p[0]];
/* n이 소수일경우. */
if(isPrime(n)){
var temp1 = n%10; //우측부터 씀.(좌측부터지우는걸 역으로)
var temp2 = parseInt(n/10); //우측부터 지움.
var check = true;
for(var j=2; temp1 < n; j++){
if(!isPrime(temp1) || !isPrime(temp2)){
check = false;
break;
}
temp1 = n % Math.pow(10, j);
temp2 = parseInt(temp2/10);
}
if(check){
sum += n;
cnt ++
}
}
/* 다음 자릿수 탐색 위치를 찾음. */
p[0] ++;
if(p[0] >= 2){
p[0] = 0;
p[1] ++;
for(var i=1; i< p.length; i++){
if(p[i] >= 4){
p[i] = 0;
if(i==p.length-1)
p[i+1] = 0;
else
p[i+1] ++;
}
else
break;
}
}
}
//결과값.
alert(sum);
}
</script>
댓글 없음:
댓글 쓰기