제곱 ㄴㄴ 수
문제의 원본은 여기서 확인하세요.
- 에라토스테네스의 체
에라토스테네스의 체를 이용하여 제곱수를 걸러낸다. 그 이후 (max - min + 1)에서 체에서 걸러내진 개수를 뺀다.
즉, min ~ max 사이의 개수에서 제곱수의 개수를 빼면 제곱 ㄴㄴ 수의 개수가 된다.
#include <iostream>
#include <cmath>
using namespace std;
bool counted[1000001] = { false };
int main(void) {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
long long min, max;
cin >> min >> max;
// 제곱수의 수
long long count = 0;
// 2부터 i^2 <= max까지 제곱수의 배수를 카운트
for (long long i = 2; i * i <= max; i++) {
// 에라토스테네스의 체에서 min 이상의 값만 검사하면 되므로,
// i^2 * n를 했을때 min 이상이 되는 첫 n를 구한다.
long long n = min / (i * i);
// n이 min 이하일경우
if (n * i * i < min) n++;
// i제곱의 배수를 카운트 (max 이하까지만)
for (long long j = n; i * i * j <= max; j++) {
// counted 배열을 위해 (min ~ max)를 0 ~ (max -min) 으로 대응
long long idx = i * i * j - min;
// 중복 카운트 방지
if (!counted[idx]) {
count++;
counted[idx] = true;
//cout << i * i * j << endl;
}
}
}
int result = (max - min + 1) - count;
cout << result << "\n";
return 0;
}