본문 바로가기

정수론

제곱 ㄴㄴ 수 (어렵)

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

 

1016번: 제곱 ㄴㄴ 수

어떤 정수 X가 1보다 큰 제곱수로 나누어 떨어지지 않을 때, 그 수를 제곱ㄴㄴ수라고 한다. 제곱수는 정수의 제곱이다. min과 max가 주어지면, min보다 크거나 같고, max보다 작거나 같은 제곱ㄴㄴ수

www.acmicpc.net

  • 1 ≤ min ≤ 1,000,000,000,000
  • min ≤ max ≤ min + 1,000,000

범위가 커 보이지만 min과 max의 사이이므로 1000000이다.

 

데이터를 순서대로 탐색하는 것이 아니라

에라토스테네스의 체의 원리를 사용하면 된다.

제곱수의 배수를 없애는 방식으로!

 

그냥 생각없이 에라토스테네스를 쓰기에는

숫자가 너무 크다 check 배열이 너무 커진다.

 

index를 0부터 max - min까지로 만들자

 

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
#include <iostream>
#include <vector>
 
using namespace std;
 
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
 
    long min, max;
    cin >> min >> max;
    vector<bool> check(max - min + 1);
 
    // 2의 제곱수인 4부터 max보다 작거나 같은 값까지 반복
    for (long i = 2; i * i <= max; i++)
    {
        long pow = i * i; // 제곱수
        long start_index = min / pow;
 
        if (min % pow != 0)
        {
            // 나머지가 있으면 1을 더해주어야 min보다 큰 제곱수부터 시작
            start_index++;
        }
 
        // 제곱수의 배수들을 이제 true로 바꾸자.
        for (long j = start_index; pow * j <= max; j++)
        {
            check[(int)((j * pow) - min)] = true;
        }
 
    }
 
    int ans = 0;
 
    for (int i = 0; i <= max - min; i++)
    {
        if (!check[i])
            ans++;
    }
    cout << ans << '\n';
 
    return 0;
}
cs

 

        long start_index = min / pow;

 
        if (min % pow != 0)
        {
            // 나머지가 있으면 1을 더해주어야 min보다 큰 제곱수부터 시작
            start_index++;
        }
 
        // 제곱수의 배수들을 이제 true로 바꾸자.
        for (long j = start_index; pow * j <= max; j++)
        {
            check[(int)((j * pow) - min)] = true;
        }

 

'정수론' 카테고리의 다른 글

오일러 피  (0) 2023.08.19
소수&팰린드롬  (0) 2023.08.02
거의 소수  (0) 2023.08.02
에라토스테네스의 체  (0) 2023.08.02