새소식

💻 Computer/🐘 Algorithm

[1456] 거의 소수 - C++

  • -


1. 문제의 추상화

A ~ B (A, B포함) 사이의 수 중에서 거의 소수를 구한다.

거의 소수란 소수를 N제곱한 수를 말한다.

 

예를 들면 $5^2 = 25$,    $5^3 =  125$,    $7^2 = 49$ 등이 문제에서 말하는 "거의 소수"이다.

 


2. 문제 계획

에라토스테네스의 체를 사용하여 소수들을 찾아낸다.

소수들의 집합을 순회하며 "거의 소수"를 찾아낸다.

 

위처럼 크게 두 가지로 나눌 수 있다.


3. 주의해야 할 점

$10^{14}$은 100조이다.

여기서 우리는 INTOVERFLOW를 조심해야 함을 알 수 있다.

 


4. 에라토스 테네스

const int Max = 10'000'000; //10^7 : 1000만
vector<bool> arr(Max+1, 1);
void decimal(){
  for(int i = 2; i * i<= Max; ++i){
    if(!arr[i]) continue;
    for(int j = i*i; j <= Max; j += i) arr[j] = 0;
  }
}

Max를 왜 1000만으로 놨을지 궁금할 수 있다.

 

$(10^7)^2 = 10^{14}$ 이기 때문에 $10^7$을 초과하는 소수는 범위에 맞는 거의 소수가 나올 수 없다!

그렇기에 우리는 에라토스테네스의 체를 통해 $10^7$승 이하의 소수를 모두 찾으면서 문제풀이를 시작한다.

 


5. 거의 소수 찾기

typedef unsigned long long int uli;

uli result = 0, a, b;

int main(){
  decimal();
  arr[0] = 0, arr[1] = 0;
  cin >> a >> b;
  for(uli i = 2; i <= Max; ++i){
    uli cnt = i;
    if(!arr[i])continue;
    while(cnt <= b/i){
      result += (cnt * i >= a);
      cnt *= i;
    }
  }
  cout << result;
  return 0;
}

INTOVERFLOW를 최대한 방지하기 위해 모두 unsigned long long int로 선언했다.

 

소수가 Check 되어있는 배열을 돌면서 거의 소수를 구하게 된다.

그런데 while 조건 부분의$\frac {b}{i}$ 부분이 이해가 안 될 거라 생각된다.

 

위 코드에서

$cnt$는 거의 소수를 말하고

$i$는 소수를 말한다.

 

$$cnt \leq \frac {b}{i}$$

$$cnt \times i \leq b$$

 

왜 필요한 걸까?

 

$10^7$이 소수는 아니지만 이걸로 예를 들어보자.

$(10^7)^2$은 $10^{14}$라 INTOVERFLOW가 될 일은 없지만

$(10^7)^3$은 $10^{21}$라 INTOVERFLOW가 된다.

 

이걸 방지하기 위한 것이다.

 

아직 이해가 되지 않는 다면 코드를 아래처럼 바꾼 후,

$i = 10^7, cnt = 10^7, b = 10^{14}, a = 1$로 두고 따라가 보도록 하자

while(cnt*i <= b){
      result += (cnt * i >= a);
      cnt *= i;
    }

6. 문제를 풀어보며

$cnt \leq \frac {b}{i}$ 와 $cnt \times i \leq b$ 이 둘은 큰 차이가 있다.

이렇게 자그마한 차이로 INTOVERFLOW를 만날 수도, 만나지 않을 수도 있음을 알았다.

'💻 Computer > 🐘 Algorithm' 카테고리의 다른 글

[1600] 말이 되고픈 원숭이 - C++  (0) 2023.08.23
[2146] 다리 만들기 - C++  (0) 2023.08.23
[2457] 공주님의 정원 - C++  (0) 2023.07.09
[2156] 포도주 시식 - C++  (0) 2023.07.02
[1520] 내리막 길 - C++  (0) 2023.06.30
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.