아래의 문제의 답을 도출하는 과정을 프로그래밍 언어로 구현하시오.(php, javascript... 뭐든 좋습니다)
완전수란 자기 자신을 제외한 약수의 합이 자기 자신과 같은 수를 말합니다.
6 의 약수 : 1,2,3,6
자기자신을 제외한 수를 더하면 1 + 2 + 3 =6 즉 자기 자신과 같아집니다.
문제 ) 10000 이하의 모든 완전수를 출력하시오.
댓글 4개
<?php
set_time_limit(0);
//ini_set('memory_limit','1G');
header('Content-Type: text/html; charset=utf-8');
/*
완전수 자체는 몇개 존재 하지 않는다.
유클리드 공식을 이용하면 쉽게 구할수 있다.
유클리드 공식에 의한 방법과
일반적인 방법 두가지방법으로 개별 처리
유클리드 방정식
2^(n-1) * (2^n - 1)
n 은 소수만 대입가능
100^100 내에서는 사실인것으로 검증됨
일반적인 방식
약수의 갯수가 4개 이상인 것만 가능
즉, 소수는 애초에 검색 대상에서 제외
약수의 합 - (자기자신 * 2) == 0
*/
function microtime_float() {
list($usec, $sec) = explode(" ", microtime());
return (((float)substr((string)$usec, 0, 4) + (float)$sec)) * 1000;
}
function get_excute_time($msg, $start_time){
$end_time = microtime_float();
$time = ($end_time - $start_time) / 1000;
echo "$msg : $time seconds" . PHP_EOL ;
}
//주어진 숫자까지 포함된 모든 소수를 구함
function get_prime ($end) {
$end = (int)$end;
$end = ($end > 100000) ? 100000 : (($end <= 10) ? 10 : $end); //100000 보다 크면 100000, 10보다 작거나 같으면 10
$prime = Array(2, 3, 5, 7);
if ($end == 10) {
return $prime;
}
for ($search = 11; $search <= $end; $search += 2) { //홀수만 대입
if (substr((string)$search, -1) == 5)// 5보다 큰 자연수 중에 5로 끝나는 소수는 없다. 모두 5로 나누어짐, 직접 나누는것보다 끝자리만 확인하는것이 더 빠를것 같아 처리
continue;
if (check_prime ($prime, $search) == true)
$prime[] = $search;
}
return $prime;
}
//기존에 가진 소수 배열로서 소수인지 판별
function check_prime ($prime, $search) {
$search = (float)$search;//float(double) 형으로 형변환
if ($search > 2 && (int)substr((string)$search, -1) % 2 == 0)// 2보다 큰 자연수 중에 0, 2, 4, 6, 8로 끝나는 소수는 없다. 모두 2로 나누어짐
return false;
if ($search > 5 && substr((string)$search, -1) == 5)// 5보다 큰 자연수 중에 5로 끝나는 소수는 없다. 모두 5로 나누어짐
return false;
$max = bcsqrt((string)$search, 1);//결과값이 문자형으로 반환, $search 가 2147483647 보다 클수 있으므로 bcsqrt
if (strpos($max, '.') === false) {//$search 는 $max 의 제곱이라는 의미
//echo "$search $max 제곱근" . PHP_EOL;
return false;
}
$max = (int)$max; //정수형으로 변환, 소수점 이하 버려짐
foreach($prime as $p){
if ($p > $max) {//비교를 위해 대입하는 소수가 비교되는 수의 제곱근보다 클수 없다.
return true;
}
else if (bcmod($search, (string)$p) == 0) {//다른소수의 배수이므로 소수가 아니다. $search 가 2147483647 보다 클수 있으므로 bcmod
//echo "$search $p 의 배수" . PHP_EOL;
return false;
}
}
return true;
}
function get_divisor ($number) {
$return = Array(1, $number);
$max = (int)sqrt($number);
for ($i = 2; $i <= $max; $i++) {
$div = $number / $i;
if ((int)$div * $i == $number) {
$return[] = $i;
$return[] = $div;
}
}
return $return;
}
function get_perfet ($search) {
$return = Array();
$prime = get_prime($search);
for($number = 2; $number <= $search; $number++) {
if (in_array($number, $prime))
continue;
$number_divisor = get_divisor ($number);
if (array_sum($number_divisor) - ($number * 2) === 0) {
$return[] = $number;
}
}
return $return;
}
function get_perfet_euclid ($search) {
$result = Array();
//적당히 큰 소수를 뽑는다
$prime = get_prime(100);
foreach($prime as $number){
$x = pow(2, $number - 1) * (pow(2, $number ) - 1);
if ($x >= $search) {
break;
}
$result[] = $x;
}
return $result;
}
$search = 10000;
$start_time = microtime_float();
$result = get_perfet ($search);
print_r($result);
get_excute_time("일반 방식으로 구한 시간", $start_time);
echo PHP_EOL;
$start_time = microtime_float();
$result = get_perfet_euclid ($search);
print_r($result);
get_excute_time("유클리드공식을 사용한 방식으로 구한 시간", $start_time);
?>
set_time_limit(0);
//ini_set('memory_limit','1G');
header('Content-Type: text/html; charset=utf-8');
/*
완전수 자체는 몇개 존재 하지 않는다.
유클리드 공식을 이용하면 쉽게 구할수 있다.
유클리드 공식에 의한 방법과
일반적인 방법 두가지방법으로 개별 처리
유클리드 방정식
2^(n-1) * (2^n - 1)
n 은 소수만 대입가능
100^100 내에서는 사실인것으로 검증됨
일반적인 방식
약수의 갯수가 4개 이상인 것만 가능
즉, 소수는 애초에 검색 대상에서 제외
약수의 합 - (자기자신 * 2) == 0
*/
function microtime_float() {
list($usec, $sec) = explode(" ", microtime());
return (((float)substr((string)$usec, 0, 4) + (float)$sec)) * 1000;
}
function get_excute_time($msg, $start_time){
$end_time = microtime_float();
$time = ($end_time - $start_time) / 1000;
echo "$msg : $time seconds" . PHP_EOL ;
}
//주어진 숫자까지 포함된 모든 소수를 구함
function get_prime ($end) {
$end = (int)$end;
$end = ($end > 100000) ? 100000 : (($end <= 10) ? 10 : $end); //100000 보다 크면 100000, 10보다 작거나 같으면 10
$prime = Array(2, 3, 5, 7);
if ($end == 10) {
return $prime;
}
for ($search = 11; $search <= $end; $search += 2) { //홀수만 대입
if (substr((string)$search, -1) == 5)// 5보다 큰 자연수 중에 5로 끝나는 소수는 없다. 모두 5로 나누어짐, 직접 나누는것보다 끝자리만 확인하는것이 더 빠를것 같아 처리
continue;
if (check_prime ($prime, $search) == true)
$prime[] = $search;
}
return $prime;
}
//기존에 가진 소수 배열로서 소수인지 판별
function check_prime ($prime, $search) {
$search = (float)$search;//float(double) 형으로 형변환
if ($search > 2 && (int)substr((string)$search, -1) % 2 == 0)// 2보다 큰 자연수 중에 0, 2, 4, 6, 8로 끝나는 소수는 없다. 모두 2로 나누어짐
return false;
if ($search > 5 && substr((string)$search, -1) == 5)// 5보다 큰 자연수 중에 5로 끝나는 소수는 없다. 모두 5로 나누어짐
return false;
$max = bcsqrt((string)$search, 1);//결과값이 문자형으로 반환, $search 가 2147483647 보다 클수 있으므로 bcsqrt
if (strpos($max, '.') === false) {//$search 는 $max 의 제곱이라는 의미
//echo "$search $max 제곱근" . PHP_EOL;
return false;
}
$max = (int)$max; //정수형으로 변환, 소수점 이하 버려짐
foreach($prime as $p){
if ($p > $max) {//비교를 위해 대입하는 소수가 비교되는 수의 제곱근보다 클수 없다.
return true;
}
else if (bcmod($search, (string)$p) == 0) {//다른소수의 배수이므로 소수가 아니다. $search 가 2147483647 보다 클수 있으므로 bcmod
//echo "$search $p 의 배수" . PHP_EOL;
return false;
}
}
return true;
}
function get_divisor ($number) {
$return = Array(1, $number);
$max = (int)sqrt($number);
for ($i = 2; $i <= $max; $i++) {
$div = $number / $i;
if ((int)$div * $i == $number) {
$return[] = $i;
$return[] = $div;
}
}
return $return;
}
function get_perfet ($search) {
$return = Array();
$prime = get_prime($search);
for($number = 2; $number <= $search; $number++) {
if (in_array($number, $prime))
continue;
$number_divisor = get_divisor ($number);
if (array_sum($number_divisor) - ($number * 2) === 0) {
$return[] = $number;
}
}
return $return;
}
function get_perfet_euclid ($search) {
$result = Array();
//적당히 큰 소수를 뽑는다
$prime = get_prime(100);
foreach($prime as $number){
$x = pow(2, $number - 1) * (pow(2, $number ) - 1);
if ($x >= $search) {
break;
}
$result[] = $x;
}
return $result;
}
$search = 10000;
$start_time = microtime_float();
$result = get_perfet ($search);
print_r($result);
get_excute_time("일반 방식으로 구한 시간", $start_time);
echo PHP_EOL;
$start_time = microtime_float();
$result = get_perfet_euclid ($search);
print_r($result);
get_excute_time("유클리드공식을 사용한 방식으로 구한 시간", $start_time);
?>
게시글 목록
| 번호 | 제목 |
|---|---|
| 5919 | |
| 5915 | |
| 5905 | |
| 5904 | |
| 5885 | |
| 5879 | |
| 5870 | |
| 5869 | |
| 5868 | |
| 5863 | |
| 5854 | |
| 5813 | |
| 5800 | |
| 5796 | |
| 5787 | |
| 5786 | |
| 5785 | |
| 5768 | |
| 5750 | |
| 5732 | |
| 5716 | |
| 5713 | |
| 5707 | |
| 5705 | |
| 5701 | |
| 5694 | |
| 5681 | |
| 5669 | |
| 5668 | |
| 5648 |
댓글 작성
댓글을 작성하시려면 로그인이 필요합니다.
로그인하기