Post

[백준] 1016번: 제곱 ㄴㄴ 수

[백준] 1016번: 제곱 ㄴㄴ 수

📌 문제

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

📌 설명

에라토스테네스의 체 알고리즘의 아이디어에 착안하여 해결하는 문제이다. $a$와 $b$ 사이에 존재하는 제곱 ㄴㄴ 수를 찾는 방법은 다음과 같다.

$a \leq x \leq b$인 $x$ 중 $x \ \text{mod}\ p^2 = 0$ 를 만족하는 $x$를 소거한다. ($p$는 2 이상인 소수)

남은 $x$가 제곱 ㄴㄴ 수이다.

📌 코드

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
#include <iostream>
#include <cmath>

using namespace std;

int arr[1000001]; // a인 수의 인덱스는 0 / 즉, 특정 수 x의 인덱스는 x - a

int main() {
	long long a, b;
	cin >> a >> b;

	// p^2으로 나누어 떨어진다면 제곱 ㄴㄴ 수가 될 수 없다. (p는 소수)
	// a부터 p^2으로 나누어 떨어지는 수들을 arr에 표기하여, b 이전까지 진행한다.
	// 즉, 표기된 수들은 제곱 ㄴㄴ 수가 될 수 없다.

	long long p = 2; // 2부터 시작
	long long ans = b - a + 1;

	while (p * p <= b) {
		// start: a보다 큰 (p * p) * k의 값 중 a와 가장 가까운 수에서의 k
		long long start = a / (p * p);
		if (start * (p * p) < a)
			start++;

		// a와 b 사이의 수 중 p * p의 배수인 수들을 표시
		while (start * (p * p) <= b) {
			// 이미 표기되었다면 스킵
			if (!arr[start * (p * p) - a]){
				arr[start * (p * p) - a] = 1;
				ans--;
			}

			start++;
		}

		p++;
	}

	cout << ans;
}
This post is licensed under CC BY 4.0 by the author.