[백준] 6588번 골드바흐의 추측

반응형
반응형

문제

1742년, 독일의 아마추어 수학가 크리스티안 골드바흐는 레온하르트 오일러에게 다음과 같은 추측을 제안하는 편지를 보냈다.

4보다 큰 모든 짝수는 두 홀수 소수의 합으로 나타낼 수 있다.

예를 들어 8은 3 + 5로 나타낼 수 있고, 3과 5는 모두 홀수인 소수이다. 또, 20 = 3 + 17 = 7 + 13, 42 = 5 + 37 = 11 + 31 = 13 + 29 = 19 + 23 이다.

이 추측은 아직도 해결되지 않은 문제이다.

백만 이하의 모든 짝수에 대해서, 이 추측을 검증하는 프로그램을 작성하시오.

입력

입력은 하나 또는 그 이상의 테스트 케이스로 이루어져 있다. 테스트 케이스의 개수는 100,000개를 넘지 않는다.

각 테스트 케이스는 짝수 정수 n 하나로 이루어져 있다. (6 ≤ n ≤ 1000000)

입력의 마지막 줄에는 0이 하나 주어진다.

출력

각 테스트 케이스에 대해서, n = a + b 형태로 출력한다. 이때, a와 b는 홀수 소수이다. 숫자와 연산자는 공백 하나로 구분되어져 있다. 만약, n을 만들 수 있는 방법이 여러 가지라면, b-a가 가장 큰 것을 출력한다. 또, 두 홀수 소수의 합으로 n을 나타낼 수 없는 경우에는 "Goldbach's conjecture is wrong."을 출력한다.

 

거의 한달만에 푼것 같다. 이 문제를

 

이 문제를 풀기 위해서는 한 가지 조건이 필요한데

그건 바로 소수를 구하는 아리스토텔레스의 체를 이용하는 방법이다.

이 방법은 단순하게 생각하면

i < n으로 생각하기 쉽지만

이렇게 문제를 풀면 시간 초과가 발생한다.

 

하는수 없이 다른 방법을 선택해서 이 문제를 해결해야 만했다.

 

그리고 나서 소수인 숫자를 구하고

구하려는 값과 이 소수를 뺀 값을 

다시 소수인지 확인하는 로직을 만들었다.

#include <bits/stdc++.h>
using namespace std;

bool suso(int n) {

  for(int i = 2;i*i<n;i++) {
    if (n%i == 0) {
      return false;
    }
  }
  return true;
}

int main(void) {    
  ios_base::sync_with_stdio(false); 
  cin.tie(NULL);
  
  
  while(true) {
  
  int n;
  bool flag = true;
  cin >> n;
  
  if (n == 0) {
    return 0;
  }

  for(int i = 3; i<=n;i+=2) {
    int a = i;
    if (suso(a)) {
      int b = n - a;
        if (suso(b) && !(b%2 == 0)) {
          cout << n << " = " << a << " + " << b << "\n";
          flag = false;
          break; 
        }
    }

  }

  if (flag) {
    cout << "Goldbach's conjecture is wrong." <<"\n";
  }

  }
}
 

문제에서 b-a가 가장 큰 값을 선택하라고 했다.

이 말은 즉, a가 작을때 발생된다는 의미와 같다.

현재 위 코드로 봤을 때, 무조건 b가 a보다 크게 나온다.

왜냐하면 처음 이 조건을 만족했을때 break로 탈출하기 때문이다.

 

마지막으로 flag의 역할은

만약 골드바흐가 틀렸다는 가정하에 만들었다.

flag = false는 죽은 코드나 다름없지만...

가독성을 위해 살려 뒀다.

 

그러면 n까지 전부 다 돌았는데도 만족하는 값이 없다면

위 문장이 리턴 된다.

 

#include <stdio.h>
bool isPrime[1000003] = { 1, };
void sieve(int N) {
	for (int i = 2; i <= N; i++)
		isPrime[i] = true;
	for (int cur = 2; cur <= N; cur++) {
		if (!isPrime[cur])
			continue;
		for (int i = 2 * cur; i <= N; i += cur)
			isPrime[i] = false;
	}
}
int main(void) {
	sieve(1000000);
	while (true) {
		int n;
		scanf("%d", &n);
		if (n == 0)
			return 0;
		for (int i = 3; ; i += 2) {
			if (isPrime[i] && isPrime[n - i]) {
				printf("%d = %d + %d\n", n, i, n - i);
				break;
			}
		}
	}
}
반응형

'알고리즘 > 백준' 카테고리의 다른 글

[백준] 14888번 연산자 끼워넣기  (0) 2020.06.27
[백준] 11048번 이동하기  (0) 2020.06.26
[백준] 1049번 기타줄  (0) 2020.06.22
[백준] 9625번 BABB번  (0) 2020.06.21
[백준] 2023번 신기한 소수  (0) 2020.06.21

댓글

Designed by JB FACTORY