Hueestory

[1016] 제곱 ㄴㄴ 수 (C++) 본문

PS(중단)/BOJ

[1016] 제곱 ㄴㄴ 수 (C++)

히명 2024. 5. 21. 14:33
#include <iostream>
#include <vector>
#include <cmath>

using namespace std;
typedef long long ll;

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

    ll min, max; cin >> min >> max;
    int cnt = 0;

    vector<bool> powcheck(max - min + 1, true);

    for (ll i = 2; i * i <= max; i++) {
        ll square = i * i;
        ll s = ((min + square - 1) / square) * square;
        for (ll j = s; j <= max; j += square)
            powcheck[j - min] = false;
    }

    for (int i = 0; i < max - min + 1; i++) {
        if (powcheck[i]) cnt++;
    }

    cout << cnt;

    return 0;
}

 

만약 max = 20 일 때 sqrt(20)을 기준으로 1*20 2*10 4*5 sqrt(20) 5*4 10*2 20*1 대칭을 이룬다.

따라서 제곱수를 판별 할 때 i의 범위를 i * i <= max로 놓는다.

 

1. 큰 수의 계산을 위해 long long을 사용한다

2. 시작 지점인 s를 설정한다

=> 만약 min이 4인 경우, i = 2일때 square = 4이고 min보다 큰 4의 배수 중 가장 작은 수를 구하려면

min + square의 square로 나누면 2가 되어버리므로 -1을 해준 후 square로 나눈다

나눈 후 몫과 square를 곱해주면 4의 배수 중 가장 작은 수가 나오게 된다

따라서 s = ((min + square - 1) / square) * square 라는 식을 세워야 한다

3. 시작 지점인 s를 설정했다면, j를 s부터 시작하여 square만큼 더하며 for문을 반복한다

=> 이때 j += square는 i의 2승, i의 3승, ... 을 의미한다

 

 

for문의 시간복잡도가 초과되어 시간 초과가 났던 문제

'PS(중단) > BOJ' 카테고리의 다른 글

[1934] 최소공배수 (C++)  (0) 2024.05.23
[11689] GCD(n, k) = 1 (C++)  (0) 2024.05.22
[1747] 소수&팰린드롬 (C++)  (0) 2024.05.21
[1456] 거의 소수 (C++)  (0) 2024.05.21
[1929] 소수 구하기 (C++)  (0) 2024.05.16
Comments