코딩테스트 대비를 위해 도움이 될만한 문제 추천 블로그가 있어서 이 단계대로 코테를 준비합니다.

참조 사이트: http://covenant.tistory.com/224

 

코딩테스트 대비를 위한 백준 문제 추천

코딩테스트 대비를 위한 백준 문제 추천 끝 없는 훈련만이 실전에서 흐트럼없이 정답을 향해서 움직일 수 있습니다. (Photo by Specna Arms on Unsplash) 작년 한 해 수많은 코딩테스트를 직접 경험하고

covenant.tistory.com

Part 1 준비운동 - 최소, 최대 (백준 10818)

문제 출처: https://www.acmicpc.net/problem/10818

 

10818번: 최소, 최대

첫째 줄에 정수의 개수 N (1 ≤ N ≤ 1,000,000)이 주어진다. 둘째 줄에는 N개의 정수를 공백으로 구분해서 주어진다. 모든 정수는 -1,000,000보다 크거나 같고, 1,000,000보다 작거나 같은 정수이다.

www.acmicpc.net

 

풀이

벡터를 이용해 간단히 풀었습니다. 시간이 꽤 걸리는 것 같아서 시간을 줄여주기 위해 8,9행 코드를 추가하고 c++특성상 개행 처리를 위한 'endl' 사용이 시간이 많이 소요되므로 '\n'으로 바꿔주었습니다.

굳이 vector or 배열을 사용하지 않고 구현하려면 간단하게 max변수 -1000001, min 변수 1000001을 이용하여 입력받는 값마다 min,max value값을 얻어내면 됩니다.

 

코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
 
int main()
{
    cin.tie(0);
    cin.sync_with_stdio(false);
    int n,num;
    vector<int>v;
    cin >> n;
    for (int i = 0; i < n; i++) {
        cin >> num;
        v.push_back(num);
    }
    sort(v.begin(), v.end());
    cout << v[0<< " " << v[n - 1<< '\n';
    return 0;
}
cs

 

결과

 

 

코딩테스트 대비를 위해 도움이 될만한 문제 추천 블로그가 있어서 이 단계대로 코테를 준비합니다.

참조 사이트: http://covenant.tistory.com/224

 

코딩테스트 대비를 위한 백준 문제 추천

코딩테스트 대비를 위한 백준 문제 추천 끝 없는 훈련만이 실전에서 흐트럼없이 정답을 향해서 움직일 수 있습니다. (Photo by Specna Arms on Unsplash) 작년 한 해 수많은 코딩테스트를 직접 경험하고

covenant.tistory.com

Part 1 준비운동 - 이진수 (백준 3460)

문제 출처: https://www.acmicpc.net/problem/3460

 

3460번: 이진수

양의 정수 n이 주어졌을 때, 이를 이진수로 나타냈을 때 1의 위치를 모두 찾는 프로그램을 작성하시오. 최하위 비트(least significant bit, lsb)의 위치는 0이다.

www.acmicpc.net

 

풀이

많은 랭커분들이 쉬프트연산자(<<, >>)와 비트연산자(&, |, ^)를 이용해 한두줄 남짓 코드로 작성하셨던데 

비트마스크 관련 문제를 풀게 아니라면 그냥 제 코드처럼 직관적으로 작성하는 것도 괜찮다고 생각합니다.

 

코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include<iostream>
using namespace std;
int main()
{
    int t, n, cnt;
    cin >> t;
    for(int i=0;i<t;i++){
        cin >> n;
        cnt = 0;
        while (n != 0) {
            if (n % 2 == 1)cout << cnt << " ";
            cnt++;
            n /= 2;
        }
        cout << '\n';
    }
    return 0;
}
cs

 

결과

 

 

코딩테스트 대비를 위해 도움이 될만한 문제 추천 블로그가 있어서 이 단계대로 코테를 준비합니다.

참조 사이트: http://covenant.tistory.com/224

 

코딩테스트 대비를 위한 백준 문제 추천

코딩테스트 대비를 위한 백준 문제 추천 끝 없는 훈련만이 실전에서 흐트럼없이 정답을 향해서 움직일 수 있습니다. (Photo by Specna Arms on Unsplash) 작년 한 해 수많은 코딩테스트를 직접 경험하고

covenant.tistory.com

Part 1 준비운동 - 약수구하기 (백준 2501)

문제 출처: https://www.acmicpc.net/problem/2501

 

풀이

2년전 알고리즘 문제를 처음 풀 때의 저의 풀이를 보니 길이가 10001인 배열을 선언해놓고 풀었었는데 그럴필요 없이 직관적으로 쉽게 풀 수 있습니다.

자세한 설명은 생략합니다.

 

코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
using namespace std;
int main()
{
    int n, k, i, c = 0;
    cin >> n >> k;
 
    for (i = 1; i <= n; i++)
    {
        if (n % i == 0)
            c++;
        if (c == k)
            break;
    }
    if (i <= n)
        cout << i << endl;
    else
        cout << 0 << endl;
}
cs

결과

 

 

 


문제출처: https://www.acmicpc.net/problem/2981


풀이

주어진 예제 케이스를 보면, 3개의 수를 정렬 시킨 뒤, 인접한 수의 차를 구한 뒤 그 수들의 최대공약수의 공약수가 정답임을 알 수 있습니다.

이를 검증해 보기 위해 몇가지 테스트 케이스를 만들어서 확인해보았습니다.


1) 8, 14, 17 

 -> 인접한 수의 차 : 6, 3

 -> 최대 공약수: 3

 -> 최대 공약수의 공약수: 3(정답)


2) 8, 12, 22

 -> 인접한 수의 차: 4, 10

 -> 최대 공약수: 2

 -> 최대 공약수의 공약수: 2(정답)


3) 17, 35 ,50 

 -> 인접한 수의 차: 18, 15

 -> 최대 공약수: 3

 -> 최대 공약수의 공약수: 3(정답)


4개, 5개의 숫자의 경우에도 확인해 보았는데 모두 맞았습니다. 따라서 아래의 순서대로 풀이를 진행하면 됩니다. 

1. 입력된 숫자들을 정렬하기

2. 인접한 숫자들끼리의 차를 구한 뒤 그 숫자들의 최대 공약수 구하기 ( 유클리드 호제법 이용)

3. 최대 공약수의 공약수 구하기


주의할 점은 3번 과정 중 반복문의 조건 에서 i의 범위를 주의해야합니다. 수의 최댓값이 10억이므로 계산과정에 따라 시간초과가 날 수 있습니다.

따라서 i의 범위를 줄여서 중복되는 계산 과정을 생략 할 수 있도록 합니다.


코드

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
47
48
49
50
51
52
53
54
55
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
int arr[100];
int func(int a, int b);
int main()
{
    vector<int>v;
 
    int n;
    cin >> n;
    for (int i = 0; i < n; i++)
        cin >> arr[i];
    sort(arr, arr + n);
    int gcd = arr[1- arr[0];
    for (int i = 2; i < n; i++)
    
         gcd = func(gcd, arr[i] - arr[i - 1]);
    
    //gcd=최대 공약수
    
    //최대 공약수의 공약수 => 답
    for (int i = 1; i * i <= gcd; i++)
    {
        if (i == 1)    
            v.push_back(gcd);
        else
        {
            if (gcd % i == 0) {
                v.push_back(gcd / i);
                //같은 수를 걸러내는 작업
                if((gcd/i)!=i)
                v.push_back(i);
            
            }
        }
    }
    sort(v.begin(), v.end());
    for (int i = 0; i < v.size(); i++)
        cout << v[i] << " ";
    cout << '\n';
    return 0;
}
int func(int a, int b)
{
    int c;
    while (b)
    {
        c = a;
        a = b;
        b = c % a;
    }
    return a;
}
cs


결과

  



'문제풀이(BOJ) > 수학' 카테고리의 다른 글

[백준 17206] 준석이의 수학 숙제  (0) 2020.03.11
[백준 13301] 타일 장식물  (0) 2020.03.11
[백준 11051] 이항 계수 2  (0) 2020.02.10
[백준 1339] 단어 수학  (0) 2020.02.09
[백준 11444] 피보나치 수6  (0) 2020.01.19


문제출처: https://www.acmicpc.net/problem/1676


풀이

도대체 어떻게 풀 수 있는 문제일까 고민을 많이 했는데 딱히 떠오르지 않아서 구글링을 통해 10은 2*5으로 이루어진다는 힌트만 얻고 대충 1!부터 10!부터 노트에 적어보며 규칙성을 찾아보았습니다. (사실 위의 힌트가 정답의 전부입니다.)


1!= 1*1

2!= 2*1

3!= 3*2*1

4!= 4*3*2*1

5!= 5*4*3*2*1

6!= 6*5*4*3*2*1

7!= 7*6*5*4*3*2*1

8!= 8*7*6*5*4*3*2*1

9!= 9*8*7*6*5*4*3*2*1

10!= 10* 9*8*7*6*5*4*3*2*1


이렇게 펼쳐본다음 위에서 얻은 힌트를 이용해서 팩토리얼을 구성하는 숫자들을 2와 5로 쪼개어 보았습니다. 그리고 쪼갠 숫자들을 나열하여 2와 5가 각각 몇번 나오는 지를 세어보았습니다.


2!= 2*1 => 2: 1개, 5: 0개

3!= 3*2*1 => 2: 1개, 5: 0개

4!= 2*2*3*2*1 => 2: 3개, 5: 0개

5!= 5*2*2*3*2*1 => 2: 3개, 5: 1개

6!= 2*3*5*2*2*3*2*1 => 2: 4개, 5: 1개

7!= 7*2*3*5*2*2*3*2*1 => 2: 4개, 5: 1개

8!= 2*2*2*7*2*3*5*2*2*3*2*1 => 2: 7개, 5: 1개

9!= 9*2*2*2*7*2*3*5*2*2*3*2*1 => 2: 7개, 5: 1개

10!= 2*5*9*2*2*2*7*2*3*5*2*2*3*2*1 => 2: 8개, 5: 2개


1!~ 10! 까지 계산된 수를 모두 구해서 정답을 구해보면 위의 규칙성 중 팩토리얼 숫자 중 2로 구성된 수의 갯수와 5로 구성된 수의 갯수 중 더 적은 갯수와 일치함을 알 수 있습니다.

알고리즘을 알았으니 반복문을 통해 식을 작성할 텐데 각 팩토리얼 수의 2와 5의 갯수를 구하는 식은 아래 소스코드에 나와있습니다.


코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
    cin.tie(0);
    cin.sync_with_stdio(false);
    int n;
    int two = 0, five = 0;
    cin >> n;
    
    for (int i = 2; i <= n; i = i * 2)
    
        two += n / i;
    for (int i = 5; i <= n; i = i * 5)
        five += n / i;
 
    cout << min(two, five);
    
    return 0;
}
cs


결과




'문제풀이(BOJ) > 규칙찾기' 카테고리의 다른 글

[백준 14954] Happy Number  (0) 2020.03.10
[백준 1652] 누울 자리를 찾아라  (2) 2020.01.15
[백준 1855] 암호  (0) 2020.01.06
[백준 3076] 상근이의 체스판  (0) 2020.01.03
[백준 1551] 수열의 변화  (0) 2020.01.03

문제출처: https://www.acmicpc.net/problem/17206


풀이

그냥 단순히 3또는 7의 배수인 수를 구해서 정답을 구하면 100%시간초과가 뜹니다.

테스트케이스가 최대 10만번인데 입력범위가 최대 8만 까지이므로

T가 10만이고 모든 테스트케이스의 N이 8만인 최악의 경우 최대 80억번 연산을 해야합니다.

따라서 저는 연산 전 미리 10만까지의 수에 대해 배열에 그 값까지의 합을 구해놓고 풀었습니다.

예를들어 N이 49면 temp[49]는 3부터 49까지의 수 중 3또는 7의 배수일 때 그 수들의 합을 미리 저장해서 답만 출력시키게끔 했습니다.

이렇게 하면 최대 연산횟수를 80억번에서 18만번으로 떡락시킬 수 있습니다.


코드

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
#include<iostream>
#include<algorithm>
using namespace std;
int arr[100001];
int main()
{
    cin.tie(0);
    cin.sync_with_stdio(false);
    int t, temp=0, sum = 0;
    for (int i = 3; i <= 80000; i++)
    {
        if (i % 3 == 0 && i % 7 == 0)
        {
            temp += i;
        }
        else if (i % 3 == 0)
        {
            temp += i;
 
        }
        else if (i % 7 == 0)
            temp += i;
        arr[i] = temp;
    }
    cin >> t;
    for (int i = 0; i < t; i++)
    {
        cin >> temp;
        cout << arr[temp] << '\n';
    }
 
}
cs


결과



'문제풀이(BOJ) > 수학' 카테고리의 다른 글

[백준 2981] 검문  (0) 2020.08.27
[백준 13301] 타일 장식물  (0) 2020.03.11
[백준 11051] 이항 계수 2  (0) 2020.02.10
[백준 1339] 단어 수학  (0) 2020.02.09
[백준 11444] 피보나치 수6  (0) 2020.01.19

문제출처: https://www.acmicpc.net/problem/13300


풀이

2개의성별, 6개의 학년이 있기 때문에 총 12가지의 경우가 생깁니다. 2차원 배열이 바로 떠올랐고 이를 이용해 간단하게 풀 수 있었습니다.

필요한 방의 갯수는 성별/학년 별로 학생의 수가 저장된 배열값에서 k로 나눈 몫+나머지 입니다.


코드

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
#include<iostream>
using namespace std;
int stu[2][6];
int main()
{
    int n, k, s, y, cnt = 0;
    cin >> n >> k;
    for (int i = 0; i < n; i++)
    {
        cin >> s >> y;
        stu[s][y - 1]++;
    }
    for (int i = 0; i < 2; i++)
    {
        for (int j = 0; j < 6; j++)
        {
            //나눈 몫= 방의개수
            cnt += stu[i][j] / k;
            //나머지있을시 방의개수+1
            if (stu[i][j] % k != 0)
                cnt++;
        }
    }
    cout << cnt << endl;
}
cs


결과












문제출처: https://www.acmicpc.net/problem/13301


풀이

피보나치 수열+ 규칙찾기 문제입니다.

시작인덱스를 0으로 잡으면 N번째 수는 arr[n-1]이고, 이 것을 이용해 둘레를 구해보면

n번째 수*2+ (n번째 수+n-1번째 수)*2가 됩니다.


코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include<iostream>
using namespace std;
long long arr[81];
 
int main()
{
    arr[0= 1;
    arr[1= 1;
    for (int i = 2; i < 80; i++)
        arr[i] = arr[i - 1+ arr[i - 2];
    int n;
    cin >> n;
    cout << arr[n - 1* 2 + (arr[n - 1+ arr[n-2]) * 2 << endl;
 
}
cs


결과


'문제풀이(BOJ) > 수학' 카테고리의 다른 글

[백준 2981] 검문  (0) 2020.08.27
[백준 17206] 준석이의 수학 숙제  (0) 2020.03.11
[백준 11051] 이항 계수 2  (0) 2020.02.10
[백준 1339] 단어 수학  (0) 2020.02.09
[백준 11444] 피보나치 수6  (0) 2020.01.19

+ Recent posts