• 생각

처음 풀어보니 시간초과가 떴다. 다른 사람이 잘 정리해놓은 것을 가져왔다. (링크)

 

문제에서 매우매우 중요한 키워드가 두 개 있다.

첫 번째로 'M이 하나 이상 존재하는 경우로만 주어진다' 이다.

두 번째로 '나머지가 모두 같게 되는 M을 찾으려고 한다' 이다.

 

이 두 문장을 잘 생각해보면 다음과 같다. '나머지가 같은 경우는 반드시 존재하며 이 때의 M은 모든 수에서 동일하다.'

그러면 모든 수에서 '동일하다'라는 의미는 결과적으로 M은 공약수라는 말 아니겠는가?

 

즉, 위 문제의 예제로 보면 이렇다는 것이다.

6 / M + r

34 / M + r

38 / M + r

 

여기서 r은 모두 같다는점. 즉, r만 0으로 만들 수 있다면 M을 쉽게 구할 수 있다는 것이다. 

 

(6 / M + r) - (34 / M + r) 을 풀어서 다시 묶어 표현하면

(6 - 34) / M 이라는 식이 나온다.

 

다음으로 (34 / M + r) - (38 / M + r) 을 풀어서 다시 묶어 표현하면

(34 - 38) / M 이라는 식이 나온다.

 

그리고 M은 모두 같다는 의미는 앞서 말했듯 (6 - 34) / M 라는 식과, (34 - 38) / M 의 M이 같다는 말이고,

다르게 표현하면 M은 (6 - 34)와 (34 - 38)의 공약수라는 의미라는 것.

 

 

만약 다른 예제로 17, 34, 24, 52, 39 가 있으면,

(17 - 34)와 (34 - 24)와 (24 - 52)와 (52 - 39)의 공약수를 찾으면 된다는 것이다.

 

 

그러면 이제 공약수를 찾을 일만 남았다. 공약수를 찾는 방법은 매우 쉽지 않은가?

최대공약수가 무엇인가? 최대공약수는 '공약수들 중에서 가장 큰 값' 아니던가. 즉, 거꾸로 최대공약수를 찾고 최대공약수와 그의 약수들을 구하면 끝이다.

 

  • 코드

정답 코드 : 유클리드 호제법을 이용하여 구현했다.

 

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;

public class Main {
	static int N, M;
	static StringBuilder sb;

	public static void main(String[] args) throws Exception {
		SetData();
		System.out.println(sb);
	}

	private static void SetData() throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		N = Integer.parseInt(br.readLine());
		sb = new StringBuilder();
		int[] array = new int[N];	
		
		for(int i = 0; i < N ; i++) 
			array[i] = Integer.parseInt(br.readLine());
		 
		Arrays.sort(array);		 
		int gcdValue = array[1] - array[0];	// 음수가 되지 않도록 큰 수에서 작은 수로 빼줌
	 
		for(int i = 2; i < N; i++) {
			// 직전의 최대 공약수와 다음 수(array[i] - array[i - 1])의 최대공약수를 갱신 
			gcdValue = getGCD(gcdValue, array[i] - array[i - 1]);
		}
	
		for(int i = 2; i <= gcdValue; i++) {
			// i가 최대공약수의 약수라면 출력
			if(gcdValue% i == 0) {
				sb.append(i + " ");
			}
		}
	}

	private static int getGCD(int p, int q) {
		if (q == 0) {
			return p;
		}
		return getGCD(q, p % q);
	}

}

'algorithm' 카테고리의 다른 글

[JAVA] 백준 2302번 : 극장 좌석  (0) 2020.12.22
[JAVA] 백준 2294번 : 동전 2  (0) 2020.12.21
[JAVA] 백준 1739번 : 타일링  (0) 2020.12.18
[JAVA] 백준 11058번 : 크리보드  (0) 2020.12.18
[JAVA] 백준 11047번 : 동전 0  (0) 2020.12.17

 


 

  • 생각

octorbirth.tistory.com/243여기를 통해 이해하였다.

 

2 * N 직사각형이 주어질 때, 2×1과 2×2 타일로 채우는 방법의 수

[구현]

Dynamic Programming (DP) 이용.

▶ DP[i] = 2 * i 직사각형에서 방법의 수

3 ≤ i 일 때, DP[i]는 DP[I-1]에서 크기  『1』만큼 늘어났기에 

 을 놓는 경우입니다.

① DP[i-1]에서 2*1 크기의 을 놓는 경우입니다.

     ■ 영역은 작은 단계에서 부터 쌓여온것이기 때문에 어떤 형태든 신경쓰지 않습니다.

② DP[i-2]에서 2*2 크기의  1개 or 2*1 크기의 를 2개 놓는 경우입니다. 

    → DP[i-2] * 2 

▶ DP[i] = DP[i-1] + (DP[i-2] × 2)

※ 0 ≤ n ≤ 250이기 때문에 Java의 경우 BigInteger 이용.

※ 문제 조건상 i = 0일 때, DP[0] = 0도 정의

 

 

  • 코드

정답 코드 : 점화식으로 구현하였다.

 

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.math.BigInteger;
import java.util.Scanner;
import java.util.StringTokenizer;

public class Main {
	static StringBuilder sb;
	static BigInteger[] dp;

	public static void main(String[] args) throws Exception {
		SetData();
		System.out.println(sb);
	}

	private static void SetData() throws Exception {
        Scanner sc = new Scanner(System.in);
		
		dp = new BigInteger[251];
		sb = new StringBuilder();
		
        dp[0] = new BigInteger("1"); 
        dp[1] = new BigInteger("1");
        dp[2] = new BigInteger("3");
        for(int i=3; i<=250; i++) {
            dp[i] = dp[i-2].multiply(new BigInteger("2"));
            dp[i] = dp[i].add(dp[i-1]);
        }
        
        while(sc.hasNextInt()){
            int n = Integer.parseInt(sc.next());
            sb.append(dp[n] + "\n");
         }
	}
}

'algorithm' 카테고리의 다른 글

[JAVA] 백준 2294번 : 동전 2  (0) 2020.12.21
[JAVA] 백준 2981번 : 검문  (0) 2020.12.21
[JAVA] 백준 11058번 : 크리보드  (0) 2020.12.18
[JAVA] 백준 11047번 : 동전 0  (0) 2020.12.17
[JAVA] 백준 16120번 : PPAP  (0) 2020.12.17

 


 

  • 생각

먼저 1번부터 N번째 입력했을때 최댓값의 메모를위한 dp[N+1]부터 만들어 놓자.

 

N번째의 입력은 1번째버튼을 입력하거나 4번째 버튼을 입력해야한다.

1번째 입력을 했다 가정하고 dp[i]=dp[i-1]로 초기화를 한다.

4번째 버튼을 입력할땐 몇번 연속 4번째 버튼을 입력하였는지가 중요하다.

왜냐하면 4번째 버튼을 처음 입력하기 2개전의 값이 버퍼에 복사되고 

dp[i]=dp[k]*(4번째버튼 입력횟수+1)이 되기 때문이다.

 

  • 코드

정답 코드 : 점화식을 찾아 구현하였다.

 

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class Main {
	static int N;
	static long[] dp;

	public static void main(String[] args) throws Exception {
		SetData();
		FindMaxValue();
		System.out.println(dp[N]);
	}

	private static void SetData() throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		N = Integer.parseInt(br.readLine());
		dp = new long[101];
	}

	public static void FindMaxValue() {
		for(int i = 1; i <= N; i++) {
			dp[i]=dp[i-1]+1;
			for(int j = 1; j <= i - 3; j++) {
				dp[i] = Math.max(dp[i], (j+1)*dp[i-(j+2)]);
			}
		}
	}

}

'algorithm' 카테고리의 다른 글

[JAVA] 백준 2981번 : 검문  (0) 2020.12.21
[JAVA] 백준 1739번 : 타일링  (0) 2020.12.18
[JAVA] 백준 11047번 : 동전 0  (0) 2020.12.17
[JAVA] 백준 16120번 : PPAP  (0) 2020.12.17
[JAVA] 백준 6588번 : 골드바흐의 추측  (0) 2020.12.16

 


 

  • 생각

동전을 정렬해준 뒤 가장 큰 M보다 작은 동전부터 맞춰나가며 몇개의 동전이 필요한지 세주면 최소의 동전 수로 M을 맞출 수 있을 것이다. 이 문제에선 오름차순으로 알아서 입력이 되니 뒤의 index부터 확인을 해주면 될 것 같다.

 

  • 코드

정답 코드 : 가장 큰 동전부터 맞는 수만큼 count를 세주어가며 M을 맞춰 나갔다.

 

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class Main {
	static int N, M, count;
	static int[] array;

	public static void main(String[] args) throws Exception {
		SetData();
		FindMinCount();
		System.out.println(count);
	}

	private static void SetData() throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());
		
		N = Integer.parseInt(st.nextToken());
		M = Integer.parseInt(st.nextToken());
		count = 0;
		array = new int[N];

		for (int i = 0; i < N; i++) 
			array[i] = Integer.parseInt(br.readLine());
		
	}

	public static void FindMinCount() {
		// 가장 큰 돈부터 채워나가면 최소의 동전 수로 원하는 값을 채울 수 있다.
        for(int i = N-1; i>=0; i--){
            if(M>=array[i]){
                count += M/array[i];
                M = M%array[i];
            }            
        }
	}

}

 


 

  • 생각

PPAP는 P로 바꿀 수 있다. 예) PPPAPAP는 PPPAPAP 굵은 부분을 P로 바꾸면 PPAP가 되니 PPAP 문자열이다.

 

기본적으로 이렇게 PPAP를 replace시켜 P로 바꿔주면 결과는?? 틀렸다고 뜬다.

이유는 PPAP를 P로 바꾸면서 또다시 PPPAPAP와 같은 문자열이 만들어질 수 있기 때문이다.

 

생각해낸 다른 방법은 반복문을 돌리면서 PPAP로만 만들어진 문자열인지 체크를 해주어야한다.

 

풀면서 생각해봤는데 현재까지 풀어본 그리디 문제는 정렬을 하면서 푸는 문제였다. 하지만 이 문제는 정렬을 해버리면 PPAP의 순서를 제대로 알아내기 어렵기 때문에 정렬을 하면 안된다. 그래서 그리디 문제이기보단 문자열 문제느낌이 더 강한것 같다.

 

  • 코드

정답 코드 : 반복문을 돌리면서 PPAP로 만들 수 있는지 체크해 준다.

 

import java.io.BufferedReader;
import java.io.InputStreamReader;

public class Main {
	static String ppap;
	static int count;

	public static void main(String[] args) throws Exception {
		SetData();
		SearchStringPPAP();
		System.out.println(ppap);
	}

	private static void SetData() throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		ppap = br.readLine();
		count = 0;
	}
	
    public static void SearchStringPPAP() {
    	for(int i = 0; i < ppap.length(); i++) {
    		if(ppap.charAt(i) == 'P') {
    			count++;
    		} else {
    			// PPAP이면 PPAP는 P로 바꿀 수 있기 때문에 count를 -1만 해준다.
    			if(count >= 2 && ppap.length() > i + 1 && ppap.charAt(i+1) == 'P') {
    				count--;
    				i++;
    			} else {	// 현재 A인데 앞에 PP가 없으면 PPA가 되지 않기 때문에 NP를 출력
    				count = 0;
    				break;
    			}
    		}
    	}
    	
    	if(count == 1)
    		ppap = "PPAP";
    	else
    		ppap = "NP";
    }

}

 


 

  • 생각

0이 입력될때까지 숫자를 입력한 뒤 해당 수를 짝수 두개의 수로 나누어 떨어진 숫자 두개를 출력하면 된다.

 

1. 에라토스테네스의 체를 통해 소수를 찾아 둔다.

2. 1부터 반복문을 돌면서 i와 number - i 가 모두 소수이면 출력한다.

 

  • 코드

정답 코드 : 에라토스테네스의 체를 통해 소수를 찾고, 1부터 반복문을 돌면서 i와 number - i 가 모두 소수이면 출력한다.

 

import java.io.BufferedReader;
import java.io.InputStreamReader;

public class Main {
	static int N;
	static boolean[] check;
	static StringBuilder sb;

	public static void main(String[] args) throws Exception {
		SetData();
		System.out.println(sb);
	}

	private static void SetData() throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		check = new boolean[1000001];
        getPrimeNumber();
        sb = new StringBuilder();
        
        while(true) {
            int number = Integer.parseInt(br.readLine());
            if(number == 0) break;
            
            for(int i = 1; i <= number/2; i++) {
                int index1 = i;		// 소수 1
                int index2 = number - i;	// 소수 2
                if(!check[index1] && !check[index2]) {		// 둘 다 소수가 맞으
                    sb.append(number + " = " +index1 + " + " + index2 + "\n");
                    break;
                }
            }
        }
	}
	
    public static void getPrimeNumber() {
		check[0] = check[1] = true;
		for (int i = 2; i <= 1000000; i++) {
			if (check[i] == true) {
				continue;
			}
			// 해당 수로 나누어 떨어지는 수는 소수이므로 true로 check
			for (int j = i + i; j <= 1000000; j+=i) {
				check[j] = true;
			}
		}
    }

}

'algorithm' 카테고리의 다른 글

[JAVA] 백준 11047번 : 동전 0  (0) 2020.12.17
[JAVA] 백준 16120번 : PPAP  (0) 2020.12.17
[JAVA] 백준 7570번 : 줄 세우기  (0) 2020.12.16
[JAVA] 백준 1946번 : 신입 사원  (0) 2020.12.15
[JAVA] 백준 11501번 : 주식  (0) 2020.12.14

 

 


 

  • 생각

일전에 풀었던 LIS 알고리즘을 사용하여 풀었던 기억이 있어서 풀어보았지만 시간 초과가 나왔다.

 

DP로 하는 다른 방법이 생각이 나지않아서 코드를 찾아 보았다. mygumi.tistory.com/276를 토대로 이해한 결과로 코드를 작성하였다.

 

  • 코드

정답 코드 : 점화식을 찾은 뒤 구현

 

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;

public class Main {
	static int N, max;
	static int[] dp;

	public static void main(String[] args) throws Exception {
		SetData();
		System.out.println(N-max);
	}

	private static void SetData() throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        N = Integer.parseInt(br.readLine());
        dp = new int[N+1];
        max = 0;
        
        StringTokenizer st = new StringTokenizer(br.readLine());
        for (int i = 0; i < N; i++) {
        	int temp = Integer.parseInt(st.nextToken());
            dp[temp] = dp[temp-1]+1;
            max = Math.max(max, dp[temp]);
        }
	}
}

 


 

  • 생각

후보자 배열을 만들어 준 뒤 index를 서류 성적, value를 면접 성적으로하면 서류 성적으로 오름차순으로 정렬이 된다. 정렬이 된 상태에서 구해주면 구하긴 쉬워진다.

 

  • 코드

정답 코드 : index를 이용해 오름차순 정렬해준 후 답을 도출.

 

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.StringTokenizer;

public class Main {
	static int T;
	static StringBuilder sb;

	public static void main(String[] args) throws Exception {
		SetData();
		System.out.println(sb);
	}

	private static void SetData() throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = null;

        T = Integer.parseInt(br.readLine());
        sb = new StringBuilder();

        for (int i = 0; i < T; i++) {
            int N = Integer.parseInt(br.readLine());
            int[] candidates = new int[N + 1];
            for (int j = 0; j < N; j++) {
            	st = new StringTokenizer(br.readLine());
                candidates[Integer.parseInt(st.nextToken())] = Integer.parseInt(st.nextToken());
            }

            int count = 1;
            int interviewRank = candidates[1];

            for (int j = 2; j <= N; j++) {
                if (interviewRank >= candidates[j]) {
                    interviewRank = candidates[j];
                    count++;
                }
            }

            sb.append(count + "\n");
        }
	}
}

+ Recent posts