티스토리 뷰

알고리즘/백준

15711 환상의 짝꿍 C++

4567은 소수 2021. 12. 5. 22:28

https://www.acmicpc.net/problem/15711

 

15711번: 환상의 짝꿍

환상의 나라 디디랜드에서는 인연의 증표로 끈을 하나씩 가지고 있다. 그들은 지극히 평범한 방법으로 이 끈을 이용하여 어떤 두 사람이 환상의 짝꿍인지 판단하는데, 두 사람의 끈을 서로 이

www.acmicpc.net

입력으로 들어오는 두 수의 합이 소수의 합으로 만들 수 있는 지 구하는 문제입니다. 처음에 밀러라빈으로 풀려는데 계속 틀렸다 그래서 에라토스테네스 체로 확실하게 풀었습니다. (아무래도테스트 케이스 중에 수도 프라임인데 합성수인게 있는 듯 하다....)

 

2,3 은 무조건 안되는 경우, 2보다 큰 짝수는 골드바흐 추측에 의해 두 소수의 합으로 표현됩니다. (아직 참인지는 모르지만 아주 큰 수까지도 성립합니다!)

그러므로 홀수일 때만 판단하면 되는데 홀수 = 홀수 + 짝수이므로 해당 합 - 2 가 소수이면 참 아니면 거짓입니다. 짝수이면서 소수인 것은 2 뿐이기 때문입니다.

 

최대 합이 4조이므로 200만까지 에라토스테네스체를 이용해 소수를 구한 다음 판별하고자 하는 수가 200만까지 소수들로 나눠봤을 때 나눠지는지 확인합니다.

 

(밀러 라빈은 정말 왜 안 되지...??? 위키 기준으로 4조 정도면 2 ~ 17까지만 a 로 잡고 판단해도 된다 그랬는데.....)

#include <iostream>
#include <vector>
#include <algorithm>
#include <queue>
#include <cstring>
#include <cmath>

using namespace std;

int T;
long long A, B;
bool is_prime[2000001];
int max_num = 2000001;
vector<long long>primes;

void init()
{
	cin >> A >> B;
}

void yes()
{
	cout << "YES";
}

void no()
{
	cout << "NO";
}

void Eratos()
{
	memset(is_prime, true, sizeof(is_prime));

	for (int i = 2; i * i < max_num; i++) {
		if (is_prime[i] == true) {
			for (int j = i * i; j < max_num; j += i)
				is_prime[j] = false;
		}
	}

	for (int i = 2; i < max_num; i++) {
		if (is_prime[i] == true)
			primes.push_back((long long)i);
	}
}

bool check_prime(long long num)
{
	bool check = true;
	for (int i = 0; i < primes.size(); i++) {
		if (num <= primes[i])
			break;

		if (num % primes[i] == 0) {
			check = false;
			break;
		}
	}
	return check;
}

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

	// 골드바흐 추측이 참이라 가정하고
	// 짝수일 때는 항상 참 (2 제외)
	// 홀수 = 홀수 + 짝수
	// 결국 A+B - 2가 소수면 true 아니면 false
	
	// 밀러 라빈 쓰니까 틀렸다 그럼 (수도 프라임이지만 합성수인게 테스트 케이스에 있는 듯)
	// 에라토스테네스 체를 쓰자
	// 최대 4조니까 2백만까지만 에라토스테네스체로 구하자

	Eratos();

	cin >> T;
	while (T--) {

		init();

		long long sum = A + B;

		if (sum <= 3) // 무조건 안 됨
			no();
		else if ((sum & 1) == 0) // 2보다 큰 짝수
			yes();
		else {
			// 2보다 큰 홀수
			// 무조건 2 + 소수 꼴
			long long num = sum - 2;
			if (check_prime(num))
				yes();
			else
				no();
		}

		if (T != 0)
			cout << '\n';
	}
}

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

백준 9576 책 나눠주기 C++  (0) 2021.12.20
백준 1202 보석 도둑 C++  (0) 2021.12.10
백준 2529 부등호 C++  (0) 2021.12.01
백준 2661 좋은수열 C++  (0) 2021.11.28
백준 1422 숫자의 신 C++  (0) 2021.11.25
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
TAG
more
«   2024/12   »
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
글 보관함