[ICPC] Goldbach's Conjecture(2011 대전 예선)
Goldbach's Conjecture
골드바흐의 추측(Goldbach's Conjecture)는 오래전부터 알려진 정수론의 미해결 문제이다. 모든 2보다 큰 짝수는 두 개의 소수의 합으로 표시될 수 있다는 것이다. 정의나 이론이 아닌 추측인 이유는 모든 짝수에서 두 소수의 합으로 표현 가능한지는 증명되지 않았기 때문이다.
(참조 - [소수 알고리즘] 소수의 특성과 에라토스테네스의 체 http://ledgku.tistory.com/61)
예를 들어,
$$ 4 = 2 + 2 $$
$$ 6 = 3 + 3 $$
$$ 8 = 3 + 5 $$
$$ 10 = 3 + 7 = 5 + 5 $$
$$ 12 = 5 + 7 $$
$$ 14 = 3 + 11 = 7 + 7 $$
$$ 16 = 3 + 13 = 5 + 11 $$
$$ 18 = 5 + 13 = 7 + 11 $$
$$ 20 = 3 + 17 = 7 + 13 $$
$$ 22 = 3 + 19 = 5 + 17 = 11 + 11 $$
문제
문제 요약
첫 줄에는 입력의 개수가 주어진다. 주어진 짝수는 두 소수의 합으로 표현되는데 한 쌍 또는 여러 쌍의 소수의 합으로 표현되어 질 수 있다. 그 중 두 소수의 차이가 가장 작은 소수 쌍을 찾고 앞에 작은 소수가 오도록 출력한다.
풀이
- 모든 자연수는 단 하나의 소수들의 곱으로 표현된다.
- 소수를 판별하기 위해서는 주어진 자연수의 제곱근까지만 나눠지는지 검사하면 된다.
결론 : 소수 판별하기 위해서는 2~$\sqrt{N}$의 소수들로만 나눠보면 된다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | #include <iostream> #include <fstream> #include <cmath> #include <list> using namespace std; // 알고리즘 // 1. 입력값 부터 입력값의 제곱근까지의 소수를 구해서 리스트에 저장한다. // 2. 주어진 자연수가 두개의 소수의 합으로 표현되므로 입력값과 리스트에 저장된 소수의 차가 소수인지 검사하면 된다. // 3. 가장 차이가 작은 소수 쌍을 찾아야 하므로 리스트의 마지막 부터 검사한다. bool isPrime(int n); void GoldbachRecursion(list<int> lst, int num, list<int>::reverse_iterator ptr, list<int>::reverse_iterator end); void GoldbachConjecture(list<int> lst, int num); int main(){ ifstream inStream; inStream.open("input.txt"); int test_case; inStream >> test_case; for(int t=0; t<test_case; t++){ int num; inStream >> num; list<int> lst; lst.push_back(2); GoldbachConjecture(lst, num); lst.clear(); } inStream.close(); return 0; } // 입력 값 n이 소수인지 아닌지 확인하는 함수 bool isPrime(int n){ for(int i=2; i<=sqrt(n); i++){ if(n%i == 0) return false; } return true; } // 리스트의 마지막부터 처음까지 진행하며 리스트의 값과 입력값의 차가 소수인지 확인하는 함수 // 소수이면 수를 출력하고 종료한다. void GoldbachRecursion(list<int> lst, int num, list<int>::reverse_iterator ptr, list<int>::reverse_iterator end){ if(isPrime(num-(*ptr))){ cout << *ptr << " " << num-(*ptr) << endl; return; } return GoldbachRecursion(lst, num, ++ptr, end); } // 입력 값 num의 중간 값까지 소수를 구해 리스트에 저장하고 GoldbachRecursion 함수에 전달해 주는 함수 void GoldbachConjecture(list<int> lst, int num){ for(int i=3; i<=num/2; i++){ list<int>::iterator j; for(j=lst.begin(); j != lst.end(); j++){ if(i % (*j) ==0) break; } if(j==lst.end()){ lst.push_back(i); } } list<int>::reverse_iterator ptr = lst.rbegin(); list<int>::reverse_iterator end = lst.rend(); return GoldbachRecursion(lst, num, ptr, end); } | cs |
결과
'아카이브 > 알고리즘' 카테고리의 다른 글
[재귀 알고리즘] Reverse Array (배열 뒤집기) (1) | 2015.10.28 |
---|---|
[재귀 알고리즘] Linear Sum (순차합) (1) | 2015.10.28 |
[소수 알고리즘] 소수의 특성과 에라토스테네스의 체 (4) | 2015.10.10 |
Maximum Contiguous Subsequence Sum(MCSS) 알고리즘 분석 (0) | 2015.10.05 |
[알고리즘 사이트] 알고리즘 문제 풀이 사이트 (2) | 2015.07.13 |