1124. 언더프라임 본문
문제링크 : https://www.acmicpc.net/problem/1124
<입력>
두 자연수 A,B (2<=A<=B<=100,000)
<출력>
A와 B사이에 소인수 분해 했을 때 소수의 개수가 소수인 수
<풀이>
일단 소수이기 때문에 에라토스테네스의 체를 이용한다.
에라토스테네스의 체를 통해 100,000까지의 소수를 찾으며 함께
특정 수가 소수임이 확인되면 그 수의 배수들을 소수가 아니라고 처리해주는 과정에서
해당 소수로 몇 번 나누어지는지 확인한다. (소인수분해한 결과는 소수들의 곱셈이므로)
그렇게 100,000까지 진행하게 되면 10만 이하의 모든 수에 대해 소인수분해 했을 경우 몇개의 소수들의 곱으로 표현되는지 알 수 있다.
이제 소수인지 체크한 배열을 통해 A에서 B 사이의 수들 중
소인수분해 했을 때 구성되는 소수의 개수가 소수인 수들의 개수를 세주면 끝 !
- 소스 코드 -
| 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 | /*  * 시간 복잡도 : 약 O(n(logn)^2)?  * 공간 복잡도 : O(N) (check 배열 + arr 배열)  *   * 에라토스테네스의 체를 이용했습니다.  * 2부터 10만까지 탐색을 하며 해당 수( i )가 소수일 경우  * i를 제외한 i의 배수들에 대해 모두 소수가 아님을 체크해주고  * i로 나눠지는 횟수를 구해 소인수 분해했을 때의 소수의 개수를 나타내는  * arr배열의 값을 증가시켜줬습니다.  * arr[n] -> 소인수 분해 시 소수의 개수  * check[arr[n]] -> 소인수 분해 시 소수의 개수가 소수인지 여부  * 이렇게 구한 값을 바탕으로 A에서 B까지 check[arr[n]]이 true인 수들의 숫자를 count했습니다. */ #include<iostream> using namespace std; int main(void){     int A,B;     cin>>A>>B;     bool check[100002];     fill_n(check,100002,true);     check[1]=false; // 1과 0은 소수가 아님 !     check[0]=false;     int arr[100002]={0};     int result=0;     for(int i=2;i<=100000;i++){         if(check[i]){ // 만약 i가 소수라면             for(int j=i*2;j<=B;j+=i){ // i의 배수들을 찾아서                 check[j]=false; // 소수가 아님을 처리                 int curNum=j;                 while(curNum%i==0){                     curNum/=i;                     arr[j]++;                 } // 그리고 i로 나누어지는 횟수만큼 증가             }         }     }     for(int i=A;i<=B;i++){         if(check[arr[i]]) result++;     }     cout<<result<<endl; } | cs | 
'알고리즘 문제풀기 > 백준(Acmicpc)' 카테고리의 다른 글
| 1322. X와 K (0) | 2019.01.31 | 
|---|---|
| 15711. 환상의 짝꿍 (2) | 2019.01.30 | 
| 2018. 수들의 합 5 (0) | 2019.01.28 | 
| 2004. 조합 0의 개수 (0) | 2019.01.28 | 
| 2870. 수학숙제 (0) | 2019.01.25 | 
			  Comments