πŸ“ Coding Test Study/Algorithm Problem

[C++][Baekjoon][Math] 6588번 κ³¨λ“œλ°”νμ˜ μΆ”μΈ‘(feat. C++ μž…μΆœλ ₯ μ‹œκ°„ 단좕)

ibelieveinme 2022. 4. 3. 09:37
728x90

[문제]

 

6588번: κ³¨λ“œλ°”νμ˜ μΆ”μΈ‘

각 ν…ŒμŠ€νŠΈ μΌ€μ΄μŠ€μ— λŒ€ν•΄μ„œ, n = a + b ν˜•νƒœλ‘œ 좜λ ₯ν•œλ‹€. μ΄λ•Œ, a와 bλŠ” ν™€μˆ˜ μ†Œμˆ˜μ΄λ‹€. μˆ«μžμ™€ μ—°μ‚°μžλŠ” 곡백 ν•˜λ‚˜λ‘œ κ΅¬λΆ„λ˜μ–΄μ Έ μžˆλ‹€. λ§Œμ•½, n을 λ§Œλ“€ 수 μžˆλŠ” 방법이 μ—¬λŸ¬ 가지라면, b-aκ°€ κ°€μž₯ 큰

www.acmicpc.net

"4보닀 큰 λͺ¨λ“  μ§μˆ˜λŠ” 두 ν™€μˆ˜ μ†Œμˆ˜μ˜ ν•©μœΌλ‘œ λ‚˜νƒ€λ‚Ό 수 μžˆλ‹€." λŠ” κ³¨λ“œλ°”νμ˜ 좔츑이 λ§žλŠ”μ§€ ν‹€λ ΈλŠ”μ§€ ν™•μΈν•˜λŠ” 문제.

 

각 ν…ŒμŠ€νŠΈ μΌ€μ΄μŠ€μ— λŒ€ν•΄μ„œ, n = a + b ν˜•νƒœλ‘œ 좜λ ₯ν•œλ‹€. μ΄λ•Œ, a와 bλŠ” ν™€μˆ˜ μ†Œμˆ˜μ΄λ‹€. 

λ§Œμ•½, n을 λ§Œλ“€ 수 μžˆλŠ” 방법이 μ—¬λŸ¬ 가지라면, b-aκ°€ κ°€μž₯ 큰 것을 좜λ ₯ν•œλ‹€.

두 ν™€μˆ˜ μ†Œμˆ˜μ˜ ν•©μœΌλ‘œ n을 λ‚˜νƒ€λ‚Ό 수 μ—†λŠ” κ²½μš°μ—λŠ” "Goldbach's conjecture is wrong."을 좜λ ₯ν•œλ‹€.

 

[풀이]

μ‹œκ°„ μ œν•œ 1초.

ν…ŒμŠ€νŠΈ μΌ€μ΄μŠ€μ˜ κ°œμˆ˜λŠ” 100,000개.

확인해야할 짝수 μ •μˆ˜ n의 λ²”μœ„. 6 ≤ n ≤ 1000000

 

1초의 μ œν•œ μ‹œκ°„μ„ λ„˜κΈ°μ§€ μ•ŠμœΌλ €λ©΄ μ—°μ‚° νšŸμˆ˜κ°€ 1μ–΅ λ²ˆμ„ μ΄ˆκ³Όν•˜λ©΄ μ•ˆλœλ‹€.

 

ν…ŒμŠ€νŠΈ μΌ€μ΄μŠ€μ˜ κ°œμˆ˜κ°€ 100,000개이고 확인해야할 짝수 μ •μˆ˜μ˜ λ²”μœ„κ°€ 1,000,000 κΉŒμ§€μ΄λ―€λ‘œ 1λΆ€ν„° nκΉŒμ§€ λͺ¨λ“  수λ₯Ό ν™•μΈν•œλ‹€λ©΄ μ΅œμ•…μ˜ 경우 100,000 * 1,000,000 의 연산을 μˆ˜ν–‰ν•˜κ²Œ λ˜μ–΄ 100,000,000,000 = 1,000μ–΅ 번의 연산을 μˆ˜ν–‰ν•΄μ•Ό ν•œλ‹€. 이 λ•Œμ˜ μ—°μ‚° 처리 μ‹œκ°„μ€ 1000μ΄ˆκ°€ 될 것이닀. 루트nκΉŒμ§€ ν™•μΈν•œλ‹€κ³  해도 100,000 * 1,000 = 100,000,000 = 10μ–΅ 번의 연산을 μˆ˜ν–‰ν•΄μ•Ό ν•œλ‹€. 아직 10초...

 

λ”°λΌμ„œ μ—λ ˆν† μŠ€ν…Œλ„€μŠ€μ˜ 체λ₯Ό ν™œμš©ν•˜μ—¬ 문제λ₯Ό ν’€μ–΄μ•Ό 함을 μ•Œ 수 μžˆλ‹€. μ—λ ˆν† μŠ€ν…Œλ„€μŠ€μ˜ μ²΄λŠ” 2λΆ€ν„° μžμ‹ μ˜ 배수λ₯Ό λ‹€ μ§€μš°λŠ” λ°©λ²•μœΌλ‘œ μ‹œκ°„λ³΅μž‘λ„ O(N(log(logN)))λ₯Ό κ°€μ§„λ‹€. 

 

κ·ΈλŸ¬λ‚˜.......... 아무리 쀄여도 μž…μΆœλ ₯μ‹œκ°„μ„ 쀄이지 λͺ»ν•΄ μ‹œκ°„μ΄ˆκ³Όκ°€ 났닀. 그리고 1번, 2번 풀이 λͺ¨λ‘ μ•„λž˜ ꡬ문을 μΆ”κ°€ν•΄μ£Όλ‹ˆ ν•΄κ²°λ˜μ—ˆλ‹€. 이 ꡬ문을 μ•ˆμ“°κ³  ν•΄κ²°ν•˜λ €λ©΄ cin, cout λŒ€μ‹ μ— scanf, prinfλ₯Ό μ‚¬μš©ν•˜λ©΄ ν•΄κ²°κ°€λŠ₯ν•˜λ‹€. (4번 μ½”λ“œ μ°Έκ³ . 이미 Cμ–Έμ–΄λ₯Ό μ‚¬μš©ν–ˆλ‹€λ©΄ μƒκ΄€μ—†μŒ!)

cin.tie(NULL);
cout.tie(NULL);
ios_base::sync_with_stdio(false);

 

λ§ˆμΉ˜λ©΄μ„œ... C++ μž…μΆœλ ₯ μ‹œκ°„ 단좕에 κ΄€ν•˜μ—¬ μ •λ¦¬ν•΄λ³΄μžλ©΄!

 

1. cin, cout λŒ€μ‹ μ— scanf, printfλ₯Ό μ“°μž. scanfλŠ” 0.798초의 μˆ˜ν–‰μ‹œκ°„μ„ κ°€μ§€λŠ”λ°, cin은 2.051초의 μ‹œκ°„μ„ κ°–λŠ”λ‹€κ³  ν•œλ‹€.(좜처: https://2heedu.tistory.com/64)

참고둜 μœ„μ˜ ꡬ문으둜 c++κ³Ό c의 ν‘œμ€€ 슀트림의 동기화 끄면 μž…μΆœλ ₯ 속도λ₯Ό 쀄일 수 μžˆλ‹€. ν•˜μ§€λ§Œ c와 c++ μž…μΆœλ ₯ μˆœμ„œκ°€ 보μž₯λ˜μ§€ μ•Šμ•„ 두 문법을 μ„žμ–΄μΌμ„ λ•Œ, μˆœμ„œκ°€ λ’€μ„žμ—¬ λ‚˜μ˜¬ 수 있고, c++ μŠ€νŠΈλ¦Όλ“€μ˜ thread μ•ˆμ •μ„± μ—­μ‹œ 보μž₯λ˜μ§€ μ•ŠλŠ”λ‹€.

2. endl λŒ€μ‹  "\n"λ₯Ό μ“°μž. endl은 κ°œν–‰μ„ ν•  뿐 μ•„λ‹ˆλΌ λ‚΄λΆ€ 버퍼도 λΉ„μ›Œμ£Όλ―€λ‘œ "\n"보닀 속도가 λŠλ¦¬λ‹€.

 

[μ½”λ“œ] 3, 4번 μ½”λ“œκ°€ μ •λ‹΅ μ½”λ“œ!

 

1번 풀이. μ‹œκ°„μ΄ˆκ³Ό.

#include <iostream>
#include <cmath>
using namespace std;

bool canGoldBahGuess(int num);
bool isPrime(int num);

int main() {
    int num;
    while(true) {
        cin >> num;
        if (num == 0) break;
        if (!canGoldBahGuess(num)) cout << "Goldbach's conjecture is wrong.\n";
    }
    return 0;
}

bool canGoldBahGuess(int num) {
    for (int i = 3; i <= num/2; i++) {//3λΆ€ν„° ν™€μˆ˜&μ†Œμˆ˜ νŒλ³„
        if (i % 2 != 0 && isPrime(i) && (num-i) % 2 != 0 && isPrime(num - i)){
            cout << num << " = " << i << " + " << num - i << "\n";
            return true;
        }
    }
    return false;
}

bool isPrime(int num) {
    for (int i = 2; i <= sqrt(num); i++) {
        if (num % i == 0) return false;
    }
    return true;
}

 

2번 풀이. μ‹œκ°„μ΄ˆκ³Ό

#include <iostream>
#include <cmath>
using namespace std;

void MakeDecimalTable();
bool canGoldbach(int num);

const int MAX_SIZE = 1000000;
int decimalTable[MAX_SIZE + 1];

int main() {
    int num;
    bool answer = true;

    MakeDecimalTable();

    while(true) {
        cin >> num;
        if (num == 0) break;
        if (!canGoldbach(num)) cout << "Goldbach's conjecture is wrong.\n";
    }
    return 0;
}

void MakeDecimalTable() {
    fill_n(decimalTable, sizeof(decimalTable)/sizeof(int), 1);
    for (int i = 2; i <= sqrt(MAX_SIZE ); i++) {//2λΆ€ν„° μ†Œμˆ˜νŒλ³„ν•˜λŸ¬ gogo
        if (decimalTable[i] != 0) {
            for (int j = 2; i*j <= MAX_SIZE ; j++) {//κ·Έ 배수λ₯Ό λͺ¨λ‘ 0으둜 λ°”κΏˆ
                decimalTable[i*j] = 0;
            }
        }
    }
}

bool canGoldbach(int num) {
    for (int i = 3; i <= num / 2; i++) {//3λΆ€ν„° μ†Œμˆ˜ νŒλ³„
        if (decimalTable[i] && decimalTable[num - i]) {
            cout << num << " = " << i << " + " << num - i << "\n";
            return true;
        }
    }
    return false;
}

 

3번 풀이. 톡과.

#include <iostream>
#include <cmath>
using namespace std;

void MakePrimeTable();
bool canGoldbach(int num);

const int MAX_SIZE = 1000000;
int primeTable[MAX_SIZE + 1];

int main() {
    cin.tie(NULL);
    cout.tie(NULL);
    ios_base::sync_with_stdio(false);

    int num;
    bool answer = true;

    MakePrimeTable();

    while(true) {
        cin >> num;
        if (num == 0) break;
        if (!canGoldbach(num)) cout << "Goldbach's conjecture is wrong.\n";
    }
    return 0;
}

void MakePrimeTable() {//μ—λΌν† μŠ€ν…Œλ„€μŠ€μ˜ 체
    for (int i = 2; i <= sqrt(MAX_SIZE); i++) {//2λΆ€ν„° μ†Œμˆ˜νŒλ³„ν•˜λŸ¬ gogo
        if (primeTable[i] == 0) {
            for (int j = 2; i*j <= MAX_SIZE; j++) {//κ·Έ 배수λ₯Ό λͺ¨λ‘ 0으둜 λ°”κΏˆ
                primeTable[i*j] = 1;
            }
        }
    }
}

bool canGoldbach(int num) {
    for (int i = 3; i <= num / 2; i++) {//3λΆ€ν„° μ†Œμˆ˜ νŒλ³„
        if (primeTable[i] == 0 && primeTable[num - i] == 0) {
            cout << num << " = " << i << " + " << num - i << "\n";
            return true;
        }
    }
    return false;
}

 

4번 풀이. 톡과

#include <iostream>
#include <vector>
#include <cstdio>
using namespace std;

const int MAX_SIZE = 1000000;

int main() {
	vector<int> primeTable;
	bool primeNoCheckTable[MAX_SIZE + 1];
	for (int i = 2; i*i <= MAX_SIZE; i++) {//2λΆ€ν„° μ†Œμˆ˜νŒλ³„ν•˜λŸ¬ gogo
		if (!primeNoCheckTable[i]) {
			if(i != 2) primeTable.push_back(i);
			for (int j = i + i; j <= MAX_SIZE; j += i) {//κ·Έ 배수λ₯Ό λͺ¨λ‘ μ†Œμˆ˜ 확인을 λλƒˆλ‹€λŠ” 의미둜 true둜 λ°”κΏˆ
				primeNoCheckTable[j] = true;
			}
		}
	}

	int num;
	bool answer;
	while (true) {
		scanf("%d", &num);
		if (num == 0) break;
		for (int prime : primeTable) {
			if (!primeNoCheckTable[num - prime]) {
				printf("%d = %d + %d\n", num, prime, num - prime);
				answer = true;
				break;
			}
		}
		if (!answer) printf("Goldbach's conjecture is wrong.\n");
	}
	return 0;
}
728x90