티스토리 뷰
문제 링크
https://algospot.com/judge/problem/read/PASS486
algospot.com :: PASS486
비밀번호 486 문제 정보 문제 재훈이는 한 번 담배를 끊겠다고 다짐할 때마다 이메일 계정 비밀번호를 바꾸는 습관이 있습니다. 재훈이는 비밀번호를 항상 "no-smok**X**" 와 같이 정하는데, 여기서 X는 1자리 이상의 자연수입니다. 재훈이에게는 k번째로 금연을 다짐할 때는 항상 정확히 k개의 약수를 갖는 숫자로 X를 선택하는 습관이 있습니다. 예를 들어 재훈이가 12번째로 금연을 다짐했을 때 쓴 비밀번호는 no-smok486 이었습니다. 486 에
algospot.com
약수 n개를 가지고있는 숫자를 범위 low부터 high까지의 숫자들 중에서 찾아내는 문제입니다.
정수 x의 약수의 개수는 x 이전의 모든 값에 대한 약수의 개수와 가장 작은 소인수 값을 알고있으면 찾을 수 있습니다.
예를 들어 12의 약수의 개수를 알고싶고 1부터 11까지의 약수의 개수와 12를 포함한 모든 값들의 가장 작은 소인수를 알고 있습니다.

그럼 12를 12의 가장 작은 소인수인 2로 나누면 6이 됩니다.
12를 n, 6을 p라고 하고
n과 p의 가장 작은 소인수는 2로 같습니다.
이렇게 n과 p의 가장 작은 소인수가 같은 경우 p의 가장 작은 소인수의 개수를 확인합니다.

p의 가장 작은 소인수의 개수 2는 1개 입니다.
그럼 n은 p에서 공통으로 가장 작은 소인수인 2를 한번 더 곱한 값이기 때문에 n에서의 가장 작은 소인수인 2의 개수는 2개라고 할 수 있습니다.
이 값을 a라고 했을 때

다음과 같은 식으로 n의 약수의 개수를 구할 수 있습니다.
만약 n과 p의 가장 작은 소인수가 서로 다른 경우
예를 들어 6은 6의 가장 작은 소인수가 2인데 6을 2로 나눈 3의 가장 작은 소인수는 3으로 서로 다릅니다.
그러면 6의 소인수에는 2가 1개밖에 존재하지 않기 때문에 factors[3]에 2를 곱해주면 6의 약수의 개수를 구할 수 있습니다. 그러므로 a를 1로 두면 위의 식과 동일하게 적용할 수 있습니다.
이렇게 소인수의 개수를 먼저 구하는 방식으로 문제를 해결하기 위해서는 에라토스테네스의 체 알고리즘을 사용하여 1부터 주어진 최대값인 1천만 까지 각 수의 가장 작은 소인수를 먼저 구해주면 됩니다.
구현 코드
#include <iostream> | |
#include <cmath> | |
#include <cstring> | |
using namespace std; | |
//천만까지 가장 작은 소인수를 미리 minFactor에 계산 | |
const int MAX = 10000001; | |
int minFactor[MAX]; | |
//i의 소인수 분해에 들어가는 minFactor[i]의 개수 | |
int minFactorPower[MAX]; | |
int factors[MAX]; | |
void getFactorSmart(){ | |
factors[1] = 1; | |
for(int n=2;n<=MAX;++n){ | |
//소수인 경우 약수가 2개밖에 없다 | |
if(minFactor[n] == n){ | |
minFactorPower[n] = 1; | |
factors[n] = 2; | |
} | |
//소수가 아닌 경우 | |
else{ | |
//n을 n의 가장 작은 소인수로 나눈다 | |
int p = minFactor[n]; | |
int m = n / p; | |
//n과 m의 가장 작은 소인수가 서로 다른 경우에는 n의 소인수에 p가 1개만 존재한다 | |
if(p != minFactor[m]) | |
minFactorPower[n] = 1; | |
//n과 m의 가장 작은 소인수가 서로 같은 경우에는 | |
//n의 소인수에 m의 가장 작은 소인수의 개수 + 1개가 존재한다 | |
else | |
minFactorPower[n] = minFactorPower[m] + 1; | |
int a = minFactorPower[n]; | |
factors[n] = (factors[m] / a) * (a + 1); | |
} | |
} | |
} | |
//에라토스테네스의 체를 사용하여 각 수의 가장 작은 소인수 구하기 | |
void eratosthenes(){ | |
//1은 예외처리한다 | |
minFactor[0] = minFactor[1] = 1; | |
for(int i=2;i<=MAX;i++){ | |
minFactor[i] = i; | |
} | |
int sqrtn = int(sqrt(MAX)); | |
for(int i=2;i<=sqrtn;i++){ | |
if(minFactor[i] == i){ | |
for(int j=i*i;j<=MAX;j+=i){ | |
if(minFactor[j] == j) | |
minFactor[j] = i; | |
} | |
} | |
} | |
} | |
int main(){ | |
int test_case; | |
int n,low,high; | |
cin >> test_case; | |
eratosthenes(); | |
getFactorSmart(); | |
while(test_case--){ | |
int count = 0; | |
cin >> n >> low >> high; | |
for(int i=low;i<=high;i++){ | |
if(n == factors[i]){ | |
count++; | |
} | |
} | |
cout << count << endl; | |
} | |
} |
'Coding Test > 알고스팟' 카테고리의 다른 글
[C++] 알고스팟/완전탐색 - 게임판 덮기 (0) | 2020.01.11 |
---|---|
[C++] 알고스팟/완전탐색 - 소풍 (0) | 2020.01.10 |
[C++] 알고스팟/유클리드 - 마법의 약 (0) | 2020.01.08 |
[C++] 알고스팟/삼분검색 - 꽃가루 화석 (0) | 2020.01.05 |
[C++] 알고스팟/이분법 - 승률 올리기 (0) | 2020.01.05 |
- Total
- Today
- Yesterday
- 삼각형 위의 최대 경로 수 세기
- C++
- microwaving lunch boxes
- 완전탐색
- Django
- 합친 lis
- 백준
- 스파크
- 하둡
- 분할정복
- Jaeha's Safe
- hive
- 외발 뛰기
- pyspark
- HDFS
- 종만북
- 알고스팟
- 2225
- Sqoop
- 출전 순서 정하기
- 배열과 문자열
- 팰린드롬 구하기
- HiveQL
- Hadoop
- 하이브
- 삼각형 위의 최대 경로
- 코딩인터뷰 완전분석
- 두니발 박사의 탈옥
- import
- python
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |