728x90
728x90

문제 링크 : https://www.acmicpc.net/problem/1759

 

1759번: 암호 만들기

첫째 줄에 두 정수 L, C가 주어진다. (3 ≤ L ≤ C ≤ 15) 다음 줄에는 C개의 문자들이 공백으로 구분되어 주어진다. 주어지는 문자들은 알파벳 소문자이며, 중복되는 것은 없다.

www.acmicpc.net

문제

바로 어제 최백준 조교가 방 열쇠를 주머니에 넣은 채 깜빡하고 서울로 가 버리는 황당한 상황에 직면한 조교들은, 702호에 새로운 보안 시스템을 설치하기로 하였다. 이 보안 시스템은 열쇠가 아닌 암호로 동작하게 되어 있는 시스템이다.

암호는 서로 다른 L개의 알파벳 소문자들로 구성되며 최소 한 개의 모음(a, e, i, o, u)과 최소 두 개의 자음으로 구성되어 있다고 알려져 있다. 또한 정렬된 문자열을 선호하는 조교들의 성향으로 미루어 보아 암호를 이루는 알파벳이 암호에서 증가하는 순서로 배열되었을 것이라고 추측된다. 즉, abc는 가능성이 있는 암호이지만 bac는 그렇지 않다.

새 보안 시스템에서 조교들이 암호로 사용했을 법한 문자의 종류는 C가지가 있다고 한다. 이 알파벳을 입수한 민식, 영식 형제는 조교들의 방에 침투하기 위해 암호를 추측해 보려고 한다. C개의 문자들이 모두 주어졌을 때, 가능성 있는 암호들을 모두 구하는 프로그램을 작성하시오.

입력

첫째 줄에 두 정수 L, C가 주어진다. (3 ≤ L ≤ C ≤ 15) 다음 줄에는 C개의 문자들이 공백으로 구분되어 주어진다. 주어지는 문자들은 알파벳 소문자이며, 중복되는 것은 없다.

출력

각 줄에 하나씩, 사전식으로 가능성 있는 암호를 모두 출력한다.

 


 

접근 방법

전체 입력된 C개의 문자들을 우선 사전순으로 sorting 한 뒤, 그 L개를 선택했을 때 최소 모음 1개, 자음 2개가 되면 출력하는 방식이다. 

 

나는 DFS로 풀었는데, dfs 함수의 인자를 start, str 두개로 지정했다.

start 인자는 dfs 함수 안의 for문을 돌 때 사용되는데

만약 이 start 인자 없이 그냥 for 문을 매번 0부터 시작해서 돌게 되면 아래와 같은 문제가 발생한다. 

acis

acit

aciw

를 출력하고 그 다음 순서는

acst인데

acsi가 출력된다. 이유는 아래 상황에서 dfs 재귀 함수가 한 턴 끝나고 나오면서 'i'의 방문 여부가 false 로 되어 있는 상황이기 때문에

a, c, s 다음에 't'가 아니라 't'보다 인덱스가 앞서고 visited가 false인 'i'가 나오는 것이다. 

arr = {a, c, i, s, t, w}  

visited = {1, 1, 0, 1, 0, 0} 

이 부분만 주의하면 정형화된 dfs 코드이니 쉽게 코드를 짤 수 있을 것이다. 

 

import java.util.*;

public class BOJ_1759_암호만들기 {

    static boolean[] visited;
    static char[] arr;
    static int L, C;
    static boolean chk(String str){
        int cnt1 = 0; //모음
        int cnt2 = 0; //자음
        for(int i = 0; i<str.length(); i++){
            if(str.charAt(i)=='a' || str.charAt(i)=='e' || str.charAt(i)=='i' || str.charAt(i)=='o' || str.charAt(i)=='u'){
                cnt1++;
            }
            else cnt2++;
            if(cnt1>=1 && cnt2>=2) return true;
        }
        return false;
    }

    static void dfs(int start, String str){
        if(str.length()==L){
            if(chk(str)){
                System.out.println(str);
                return;
            }

        }
        for(int i = start; i<C; i++){
            if(visited[i]==false){
                str = str + arr[i];
                visited[i] = true;
                dfs(i+1, str);
                str = str.substring(0, str.length()-1);
                visited[i] = false;
            }
        }


    }



    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        L = sc.nextInt();
        C = sc.nextInt();
        arr = new char[C];
        visited = new boolean[C];


        for(int i = 0; i<C; i++){
            arr[i] = sc.next().charAt(0);
            visited[i] = false;
        }
        Arrays.sort(arr);
        String initStr = "";

        dfs(0, initStr);

    }
}

728x90
728x90

[윈도우 IP/Port 를 활용한 통신 가능 여부 확인 방법]

 

1.  특정 IP 간 통신 가능 여부 확인  : ping

  • 형식 : ping [IP]
  • 예)
$ ping 192.168.0.1

$ ping naver.com
  • 특정 IP 와의 통신 가능 여부를 확인할 수 있다. 소요되는 시간도 확인 가능하다. 
  • ICMP(Internet Control Message Protocol) 가 차단되어 있다면 응답을 얻지 못한다.
  • 네트워크 공격 이슈로 차단해 놓은 경우가 많아 추천하지 않는 방법이다.

- ping 명령어 옵션

 

2. 특정 IP의 특정 Port 접속 가능 여부 확인 : telnet, tcping

  • 형식 : telnet [IP] [Port]
  • 예)
$ telnet 192.000.000.000 1234
$ telnet naver.com 80
  • telnet이란?
    • 기본 개념은 원격 로그인 서비스이지만 서버와 클리이언트 간 통신 확인 용도로 사용된다. 
    • 데이터를 암호화하지 않고 전송해 보안에 취약하며, 원격 로그인 목적으로 사용 시에는 SSH(Secure Shell)을 대신 사용하는 추세이다.
    • 연결 시 Ctrl+Z 대신 Ctrl+']' 를 통해 텔넷 프롬프트로 접속해서 quit 하도록 한다. 
  • telnet이 비활성화 되어 있는 경우
    • 제어판>프로그램 및 기능 > Windows 기능 켜기/끄기 >텔넷 클라이언트에 체크박스 체크

 

  • 형식 : tcping [IP] [Port]
  • telnet 이 아닌 tcping 으로도 확인이 가능하다. 
$ tcping 192.168.0.1 3000

 

3. 네트워크 인터페이스의 통신 상태 : netstat

  • 형식 : netstat -an|find "[IP]:[Port]"
  • 예)
$ netstat -an|find "192.0.0.0:1234"     //특정 ip, port 오픈 여부 확인 

$ netstat -an 							//오픈된 모든 포트 정보 확인

$ netstat -ano | findstr 80   			//특정 포트 정보 확인

 

* cmd 2개를 열고 한개의 cmd 에서는 telnet 명령어를, 한개의 cmd 에서는 netstat의 명령어를 실행하여 서버-Client 간에 어디에서 방화벽이 막혀 있는지 확인 가능하다. ( 참조 : https://uutopia.tistory.com/entry/%EC%8B%A4%EB%AC%B4%EC%97%90%EC%84%9C-telnet-%EB%AA%85%EB%A0%B9%EC%96%B4%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%98%EC%97%AC-%EB%B0%A9%ED%99%94%EB%B2%BD-%ED%99%95%EC%9D%B8%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95

 

 

 


 

[패킷 경로 추적 tracert]

  • 패킷 경로 추적에 사용되는 명령어
  • 패킷이 거쳐가는 네트워크 경로 상의 장비(라우터, 스위치) 정보와 각 장비의 IP 주소 및 응답 속도를 확인할 수 있다.
  • 이를 활용해 속도 지연이 발생되는 구간을 확인할 수 있다.
  • 속도 지연이 발생되는 구간의 라우팅 경로를 변경하면 문제 해결이 될 수도 있다.
  • ping 명령어와 같이 icmp로 동작하므로 특정 경로에서 icmp 가 차단되어 있다면 정보를 얻지 못한다. (요청 시간 만료로 표시)
  • 예)
$ tracert 192.168.0.0 

$ tracert naver.com
  • 옵션
-d                 주소를 호스트 이름으로 확인하지 않습니다.
-h maximum_hops    대상 검색을 위한 최대 홉 수입니다.
-j host-list       host-list에 따라 원본 라우팅을 완화합니다(IPv4에만 해당).
-w timeout         각 응답의 대기 시간 제한(밀리초)입니다.
-R                 왕복 경로를 추적합니다(IPv6에만 해당).
-S srcaddr         사용할 원본 주소입니다(IPv6에만 해당).
-4                 IPv4를 사용합니다.
-6                 IPv6을 사용합니다.

 


 

[서버 이중화]

  • 안정적으로 무중단 서비스를 제공해야 하는 경우에 서버 두 대를 이용한다. 이를 서버 이중화 구조라고 하는데 크게 Active-Active 구조와 Active-Standby 구조로 나뉜다. 
  • Zero Down Time 을 달성하기 위함이다.  

(그림 출처  : https://haeunyah.tistory.com/122)

  • Active-Active 구조
    • 서버 두 대를 모두 이용하는 방식. 
    • 로드 밸런싱을 해주는 L4 스위치와 같은 하드웨어 장비가 클라이언트로부터 들어온 요청을 적절히 두 개의 서버에 분배한다. (최근에는 하드웨어 뿐 아니라 소프트웨어가 로드밸런서의 역할을 하기도 하나.)
    • 분배하는 기준은 번갈아가면서 주거나, / 부하가 적은 서버에 주거나, / 두 서버에 동시에 주고 응답이 빠른 서버를 선택하는 등의 여러 기준이 있다. 
      • ex. 라운드 로빈, 리스트 커넥션, 리스트 타임, 해시 등
  • Active-Standby 구조
    • 서버 두 대중 한 서버만 활용하고 나머지 한 서버는 백업용으로 장애 발생 시 원래 서버에 문제가 발생해서 down되면 백업 서버가 운영 서버로 전환되는 방식이다. 
    • 전환 시에는 자동 또는 수동으로 전환되며 이는 선택 가능하다. 
    • 평소에 Standby 서버도 Active 서버와 동일한 데이터를 가질 수 있도록 동기화 하는 작업이 필요하다. 

* 윈도우에서 서버 이중화 설정하는 방법 (NIC Teamming)

https://pinetreeday.tistory.com/202

 

WINDOW 티밍(Teamming) 네트워크 이중화 설정하는 방법

WINDOW 티밍(Teamming) 네트워크 이중화 구성 ▶ Teamming 윈도우 네트워크 이중화 테스트 실습을 위해 vmware workstation을 통해서 네트워크 어댑터를 추가해주도록 하겠습니다.(물리적인 서버의 경우는 NI

pinetreeday.tistory.com

 


 

 

[네트워크 용어]

1. Hang Up

  • Service Instance 는 실행되고 있으나 멈추는 현상을 말한다. (멈춤)

2. Slow Down

  • Service Instance 는 실행되고 있으나 Response Time이 급격히 떨어지는 상태를 말한다. (느려짐)

3. Freezing

  • Hang 과 비슷하나, Hang 과 달리 마우스는 움직일 수 있는 상황이다. 

4. DeadLock

  • Hang과 비슷하나 특정 요인에 의해 두 개 이상의 프로세스가 한정된 자원을 동시에 요청해서 모든 프로세스들이 일 처리를 하지 못하고 무한 대기 상태가 되는 것이다. 

 

 


 

[RSS]

  • RSS란?
    • RSS(Received Side Scaling)는 다중 프로세서 시스템의 여러 CPU에서 네트워크 수신 처리를 효율적으로 배포할 수 있는 네트워크 드라이버 기술이다.
    • RSS가 비활성 된 경우, 모든 프로세싱은 한개의 프로세서에서만 처리하므로 해당 프로세서의 캐시 이용률이 높아져 부하가 발생할 수 있다. 
  • RSS가 제공하는 메커니즘
    • 분산 처리
    • 순차 처리
    • 동적 부하 분산
    • 송신 쪽 크기 조정
    • 보안 해시

 

 

 

 

 

 

다음 세미나 준비 주제

 : 서버 성능 향상 방법

 (ex. spec, cpu, mem, heap,,, etc)

 

 

 

 

참고 : 

https://uutopia.tistory.com/entry/%EC%8B%A4%EB%AC%B4%EC%97%90%EC%84%9C-telnet-%EB%AA%85%EB%A0%B9%EC%96%B4%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%98%EC%97%AC-%EB%B0%A9%ED%99%94%EB%B2%BD-%ED%99%95%EC%9D%B8%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95

728x90
728x90

문제 링크 : https://www.acmicpc.net/problem/2240

 

2240번: 자두나무

자두는 자두를 좋아한다. 그래서 집에 자두나무를 심어두고, 여기서 열리는 자두를 먹고는 한다. 하지만 자두는 키가 작아서 자두를 따먹지는 못하고, 자두가 떨어질 때까지 기다린 다음에 떨어

www.acmicpc.net

 

문제

자두는 자두를 좋아한다. 그래서 집에 자두나무를 심어두고, 여기서 열리는 자두를 먹고는 한다. 하지만 자두는 키가 작아서 자두를 따먹지는 못하고, 자두가 떨어질 때까지 기다린 다음에 떨어지는 자두를 받아서 먹고는 한다. 자두를 잡을 때에는 자두가 허공에 있을 때 잡아야 하는데, 이는 자두가 말랑말랑하여 바닥에 떨어지면 못 먹을 정도로 뭉개지기 때문이다.

매 초마다, 두 개의 나무 중 하나의 나무에서 열매가 떨어지게 된다. 만약 열매가 떨어지는 순간, 자두가 그 나무의 아래에 서 있으면 자두는 그 열매를 받아먹을 수 있다. 두 개의 나무는 그다지 멀리 떨어져 있지 않기 때문에, 자두는 하나의 나무 아래에 서 있다가 다른 나무 아래로 빠르게(1초보다 훨씬 짧은 시간에) 움직일 수 있다. 하지만 자두는 체력이 그다지 좋지 못해서 많이 움직일 수는 없다.

자두는 T(1≤T≤1,000)초 동안 떨어지게 된다. 자두는 최대 W(1≤W≤30)번만 움직이고 싶어 한다. 매 초마다 어느 나무에서 자두가 떨어질지에 대한 정보가 주어졌을 때, 자두가 받을 수 있는 자두의 개수를 구해내는 프로그램을 작성하시오. 자두는 1번 자두나무 아래에 위치해 있다고 한다.

입력

첫째 줄에 두 정수 T, W가 주어진다. 다음 T개의 줄에는 각 순간에 자두가 떨어지는 나무의 번호가 1 또는 2로 주어진다.

출력

첫째 줄에 자두가 받을 수 있는 자두의 최대 개수를 출력한다.

예제 입력 1 

7 2
2
1
1
2
2
1
1

예제 출력 1 

6

 

 


접근 방법

처음에는 자두의 위치를 1) 그대로 있는 경우와 2) 옆 나무로 움직이는 경우 두 가지 케이스로 분류하려고 했으나, 자두의 위치 외에도 고려해야할 변수가 두개가 더 있었다. ( 현재 몇초인지(t)와 t초에 몇번째 자두나무에서 자두가 떨어지는지) 

즉 총 세개의 변수를 고려해야함을 알았는데

추가로 매 t초마다 하는 선택이 최선의 선택이 아니며, 그렇다고 모든 경우의 수를 다 조사해 볼 수는 없기 때문에 dp로 풀기로 했다. 

 

dp 배열 및 각 인덱스 의미는 다음과 같다. 

dp[t][w][1] : 현재 t초이며(t초 지남), t초까지 w만큼 이동했고, 그때의 자두의 현재 위치는 1일 때 -> 먹을 수 있는 자두의 최대 갯수

dp[t][w][2] : 현재 t초이며(t초 지남), t초까지 w만큼 이동했고, 그때의 자두의 현재 위치는 2일 때 -> 먹을 수 있는 자두의 최대 갯수

 

이제 및 [몇번째 자두나무에서 자두가 떨어지는지] 및 [자두의 이동 여부] 케이스를 분류해서 생각해보자.

각각 2가지 경우의 수가 있다. 

-> 1번째 자두나무에서 자두가 떨어지거나 or 2번째 자두나무에서 자두가 떨어지거나

-> 그대로 있거나 Or 옆 나무로 이동하거나

 

 

Case1. 1번째 자두나무에서 자두가 떨어질 때

경우 1) 현재 자두가 1번에 있을 때 : 자두 먹을 수 있음

//자두가 t초째에 1번 자두나무 아래에 있을 때 (자두 먹은 케이스)
dp[t][w][1] = Math.max(dp[t-1][w][1], dp[t-1][w-1][2])+ 1;

=> 해석 : 1초 전에, 안 움직이고(w그대로), 1번에 있을 때 (안 움직여서 1번 그대로)

          vs 1초 전에, 움직이고 (w-1), 2번에 있을 때(2번에 있었으니까 1번으로 옮긴것)

중에 최대값을 구하고, 거기에 1을 더한다. 1을 더한 이유는

1번째 자두나무에서 자두가 떨어지는 Case1. 일 때

현재 자두의 위치가 1번 나무 아래에 있는 경우1) 이기 때문이다. 

 

경우 2) 현재 자두가 2번에 있을 때 : 자두 못 먹음 

//자두가 t초째에 2번 자두나무 아래에 있을 때
dp[t][w][2] = Math.max(dp[t-1][w-1][1], dp[t-1][w][2]);

 

=> 해석 : 1초 전에, 움직이고 (w-1), 1번에 있을 때 (1번에 있었으니까 2번으로 옮긴 것)) 

          vs 1초 전에, 안 움직이고(w그대로), 2번에 있을 때(안 움직여서 2번 그대로)

중에 최대값을 구하고, 이번엔 1을 안 더한다. 안 더한 이유는

1번째 자두나무에서 자두가 떨어지는 Case1. 일 때

현재 자두의 위치가 2번 나무 아래에 있는 경우2) 이기 때문이다. 

 

이런 방식으로 매 시간에 따라(t가 1부터 T일때까지)

w가 1일때부터 W일때까지 dp를 채워나간다. 

 

그리고 마지막에 모든 w에 대해서 dp[T][w][1], dp[T][w][2] 값 들 중에 최대값을 구한다. 

 

import java.util.*;

public class BOJ_2240_자두나무 {
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        int T = sc.nextInt();
        int W = sc.nextInt();
        int treeArr[] = new int[1001];
        int dp[][][] = new int[T+1][W+1][3];
        treeArr[0] = 1; //맨 처음 1번 나무에서 시작
        for(int i = 1; i<=T; i++){
            treeArr[i] = sc.nextInt();
        }

        //초기 값 셋팅
        if(treeArr[1] == 1){    //1초일 때, 첫번째 자두가 1번 나무에서 떨어질 경우(초기에 자두는 1번 나무 아래 있음)
            dp[1][0][1] = 1;    //1초일 때, 0번 움직여서, 현재 위치 그대로(1)   -> 자두 1개 먹음 (안움직이고 먹음)
            dp[1][1][2] = 0;    //1초일 때, 1번 움직여서, 현재 위치 바뀌고(2로) => 자두 0개 먹음 (움직이고 못먹음)
        }
        else{                   //1초일 때, 첫번째 자두가 2번 나무에서 떨어질 경우
            dp[1][0][1] = 0;    //1초일 때, 0번 움직이고, 현재 위치 그대로(1) -> 자두 0개 먹음 (안움직이고 못먹음)
            dp[1][1][2] = 1;    //1초일 때, 1번 움직이고, 현재 위치 바뀌고(2로) -> 자두 1개 먹음 (움직이고 먹음)

        }


        for(int t = 2; t<=T; t++){

            if(treeArr[t] == 1){    //1번 자두나무에서 자두가 떨어질 때
                //w = 0일 때 (안 움직였을 때) 현재 위치에 따른 초기 값 셋팅
                dp[t][0][1] = dp[t-1][0][1] + 1;    //현재 위치 1이면 = 0번 움직이고, 현재 위치 그대로 (안 움직이고 먹음)
                dp[t][0][2] = dp[t-1][0][2];        //현재 위치 2이면 = 0번 움직이고, 현재 위치 그대로 (안 움직이고 못 먹음)

                for(int w = 1; w<=W; w++){
                    //자두가 t초째에 1번 자두나무 아래에 있을 때 (자두 먹은 케이스)
                    dp[t][w][1] = Math.max(dp[t-1][w][1], dp[t-1][w-1][2])+ 1;
                    //자두가 t초째에 2번 자두나무 아래에 있을 때
                    dp[t][w][2] = Math.max(dp[t-1][w-1][1], dp[t-1][w][2]);
                }
            }

            else{                   //2번 자두나무에서 자두가 떨어질 때
                //w = 0일 때 (안 움직였을 때) 현재 위치에 따른 초기 값 셋팅
                dp[t][0][1] = dp[t-1][0][1];        //현재 위치 1이면 = 0번 움직이고, 현재 위치 그대로 (안 움직이고  못 먹음)
                dp[t][0][2] = dp[t-1][0][2] + 1;    //현재 위치 2이면 = 0번 움직이고, 현재 위치 그대로 (안 움직이고 먹음)



                for(int w = 1; w<=W; w++){
                    //자두가 t초째에 1번 자두나무 아래에 있을 때
                    dp[t][w][1] = Math.max(dp[t-1][w][1], dp[t-1][w-1][2]);
                    //자두가 t초째에 2번 자두나무 아래에 있을 때 (자두 먹은 케이스)
                    dp[t][w][2] = Math.max(dp[t-1][w-1][1], dp[t-1][w][2]) + 1;
                }
            }


        }

        int ans = 0;    //최대 값을 구해야 함
        for(int w = 0; w<=W; w++){
            ans = Math.max(ans, Math.max(dp[T][w][1], dp[T][w][2]));
        }
        System.out.println(ans);
    }
}

 

 

 

728x90
728x90

문제 링크 : https://www.acmicpc.net/problem/6198

 

6198번: 옥상 정원 꾸미기

문제 도시에는 N개의 빌딩이 있다. 빌딩 관리인들은 매우 성실 하기 때문에, 다른 빌딩의 옥상 정원을 벤치마킹 하고 싶어한다. i번째 빌딩의 키가 hi이고, 모든 빌딩은 일렬로 서 있고 오른쪽으

www.acmicpc.net

 

문제

도시에는 N개의 빌딩이 있다.

빌딩 관리인들은 매우 성실 하기 때문에, 다른 빌딩의 옥상 정원을 벤치마킹 하고 싶어한다.

i번째 빌딩의 키가 hi이고, 모든 빌딩은 일렬로 서 있고 오른쪽으로만 볼 수 있다.

i번째 빌딩 관리인이 볼 수 있는 다른 빌딩의 옥상 정원은 i+1, i+2, .... , N이다.

그런데 자신이 위치한 빌딩보다 높거나 같은 빌딩이 있으면 그 다음에 있는 모든 빌딩의 옥상은 보지 못한다.

예) N=6, H = {10, 3, 7, 4, 12, 2}인 경우

             = 
 =           = 
 =     -     = 
 =     =     =        -> 관리인이 보는 방향
 =  -  =  =  =   
 =  =  =  =  =  = 
10  3  7  4  12 2     -> 빌딩의 높이
[1][2][3][4][5][6]    -> 빌딩의 번호
  • 1번 관리인은 2, 3, 4번 빌딩의 옥상을 확인할 수 있다.
  • 2번 관리인은 다른 빌딩의 옥상을 확인할 수 없다.
  • 3번 관리인은 4번 빌딩의 옥상을 확인할 수 있다.
  • 4번 관리인은 다른 빌딩의 옥상을 확인할 수 없다.
  • 5번 관리인은 6번 빌딩의 옥상을 확인할 수 있다.
  • 6번 관리인은 마지막이므로 다른 빌딩의 옥상을 확인할 수 없다.

따라서, 관리인들이 옥상정원을 확인할 수 있는 총 수는 3 + 0 + 1 + 0 + 1 + 0 = 5이다.

입력

  • 첫 번째 줄에 빌딩의 개수 N이 입력된다.(1 ≤ N ≤ 80,000)
  • 두 번째 줄 부터 N+1번째 줄까지 각 빌딩의 높이가 hi 입력된다. (1 ≤ hi ≤ 1,000,000,000)

출력

  • 각 관리인들이 벤치마킹이 가능한 빌딩의 수의 합을 출력한다.

 


접근 방법

이 문제는 주어진 상황만 완전탐색으로 잘 구현하면 되는 문제였다. 비교적 쉬운 문제였는데 왜 정답률이 낮나 하고 보니 자료형이 잘못되어 틀린 경우가 많을 것 같았다. (본인도 첫 제출에 틀렸다.)

 

주어진 h의 범위는 1<=h<=1,000,000,000 이다. 

Java의 정수 자료형 및 범위를 생각해보자.

 

type 범위 bit byte
byte -128 ~ +127 (-2^7 ~ 2^7-1) 8 1
short -32,768 ~ +32,767 (-2^15 ~ 2^15-1) 16 2
int -2,147,483,648 ~ +2,147,483,647 (약 20억) 32 4
long -9,223,372,036,854,775,808 ~ +9,223,372,036,854,775,807 64 8

만약 N이 80,000(최대값)일 때 높이가 차례로 1,000,000,000(1억)부터 1씩 낮아진다고 하면

1억 + (1억-1) +(1억-2) + ... + (1억-79,000) 이 될 것이다. 이 경우엔 20억이 훌쩍 넘기 때문에 answer을 int 형으로 선언하면 틀리게 된다. 자료형을 주의하자.

 

import java.util.*;
public class BOJ_6198_옥상정원꾸미기 {
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        int N = sc.nextInt();
        long[] heightArr = new long[N];
        long ans = 0;

        for(int i = 0; i<N; i++){
            heightArr[i] = sc.nextInt();
        }
        for(int i = 0; i<N-1; i++) {
            long curHeight = heightArr[i];
            for(int j = i+1; j<N; j++){
                long nextHeight = heightArr[j];
                if(curHeight<=nextHeight) break;
                else ans++;
            }
            //System.out.println(ans);
        }
        System.out.println(ans);

    }
}

 

 

 

 

728x90
728x90

문제

세계적인 호텔인 형택 호텔의 사장인 김형택은 이번에 수입을 조금 늘리기 위해서 홍보를 하려고 한다.

형택이가 홍보를 할 수 있는 도시가 주어지고, 각 도시별로 홍보하는데 드는 비용과, 그 때 몇 명의 호텔 고객이 늘어나는지에 대한 정보가 있다.

예를 들어, “어떤 도시에서 9원을 들여서 홍보하면 3명의 고객이 늘어난다.”와 같은 정보이다. 이때, 이러한 정보에 나타난 돈에 정수배 만큼을 투자할 수 있다. 즉, 9원을 들여서 3명의 고객, 18원을 들여서 6명의 고객, 27원을 들여서 9명의 고객을 늘어나게 할 수 있지만, 3원을 들여서 홍보해서 1명의 고객, 12원을 들여서 4명의 고객을 늘어나게 할 수는 없다.

각 도시에는 무한 명의 잠재적인 고객이 있다. 이때, 호텔의 고객을 적어도 C명 늘이기 위해 형택이가 투자해야 하는 돈의 최솟값을 구하는 프로그램을 작성하시오.

입력

첫째 줄에 C와 형택이가 홍보할 수 있는 도시의 개수 N이 주어진다. C는 1,000보다 작거나 같은 자연수이고, N은 20보다 작거나 같은 자연수이다. 둘째 줄부터 N개의 줄에는 각 도시에서 홍보할 때 대는 비용과 그 비용으로 얻을 수 있는 고객의 수가 주어진다. 이 값은 100보다 작거나 같은 자연수이다.

출력

첫째 줄에 문제의 정답을 출력한다.

예제 입력 1 

12 2
3 5
1 1

예제 출력 1 

8

예제 입력 2 

10 3
3 1
2 2
1 3

예제 출력 2 

4

예제 입력 3 

10 10
1 1
2 2
3 3
4 4
5 5
6 6
7 7
8 8
9 9
10 10

예제 출력 3 

10

예제 입력 4 

100 6
4 9
9 11
3 4
8 7
1 2
9 8

예제 출력 4 

45

출처


접근 방법

 

각 도시마다 1)홍보를 할 것인지 2)홍보를 하지 않을 것인지 를 정해야한다.

 

import java.util.*;

import static java.lang.Math.min;

public class BOJ_1106_호텔 {
    static class Info{
        int cost, customer;
        public Info(int _cost, int _customer){
            this.cost = _cost;
            this.customer = _customer;
        }

    }

    static int func(int N, Info[] arr, int targetC){

        int[] dp = new int[1101];
        Arrays.fill(dp, 100000);
        dp[0] = 0;

        for(int i = 0; i<N; i++){
            for(int j = 1; j<=1100; j++){
                if(j - arr[i].customer > -1){
                    dp[j] = min(dp[j], dp[j-arr[i].customer] + arr[i].cost);
                    System.out.println(dp[j]);
                }
            }
        }

        int ans = dp[targetC];

        //최소 C명을 구하는 것. C명 이상 고객을 구했을 때 더 최소 비용이 될 수도 있음
        for(int i = targetC+1; i<=1100; i++){
            ans = min(ans, dp[i]);
        }
        return ans;
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        int C = sc.nextInt();
        int N = sc.nextInt();
        //ArrayList<Info> arr = new ArrayList<>();
        Info[] arr = new Info[1200];

        for(int i = 0; i<N; i++){
            int cost = sc.nextInt();
            int customer = sc.nextInt();
            arr[i] = new Info(cost, customer);

        }
        int answer = func(N, arr, C);
        System.out.println(answer);

    }
}

 

 

참고/ 출처 : https://kangwlgns.tistory.com/97

728x90
728x90
 

문제

정보문화진흥원 정보 영재 동아리에서 동아리 활동을 하던 영수와 민혁이는 쉬는 시간을 틈타 숫자야구 게임을 하기로 했다.

  • 영수는 1에서 9까지의 서로 다른 숫자 세 개로 구성된 세 자리 수를 마음속으로 생각한다. (예: 324)
  • 민혁이는 1에서 9까지의 서로 다른 숫자 세 개로 구성된 세 자리 수를 영수에게 묻는다. (예: 123)
  • 민혁이가 말한 세 자리 수에 있는 숫자들 중 하나가 영수의 세 자리 수의 동일한 자리에 위치하면 스트라이크 한 번으로 센다. 숫자가 영수의 세 자리 수에 있긴 하나 다른 자리에 위치하면 볼 한 번으로 센다.

예) 영수가 324를 갖고 있으면 

  • 429는 1 스트라이크 1 볼이다.
  • 241은 0 스트라이크 2 볼이다.
  • 924는 2 스트라이크 0 볼이다.
  • 영수는 민혁이가 말한 수가 몇 스트라이크 몇 볼인지를 답해준다.
  • 민혁이가 영수의 세 자리 수를 정확하게 맞추어 3 스트라이크가 되면 게임이 끝난다. 아니라면 민혁이는 새로운 수를 생각해 다시 영수에게 묻는다.

현재 민혁이와 영수는 게임을 하고 있는 도중에 있다. 민혁이가 영수에게 어떤 수들을 물어보았는지, 그리고 각각의 물음에 영수가 어떤 대답을 했는지가 입력으로 주어진다. 이 입력을 바탕으로 여러분은 영수가 생각하고 있을 가능성이 있는 수가 총 몇 개인지를 알아맞혀야 한다.

아래와 같은 경우를 생각해보자.  

  • 민혁: 123
  • 영수: 1 스트라이크 1 볼.
  • 민혁: 356
  • 영수: 1 스트라이크 0 볼.
  • 민혁: 327
  • 영수: 2 스트라이크 0 볼.
  • 민혁: 489
  • 영수: 0 스트라이크 1 볼.

이때 가능한 답은 324와 328, 이렇게 두 가지이다.

영수는 동아리의 규율을 잘 따르는 착한 아이라 민혁이의 물음에 곧이곧대로 정직하게 답한다. 그러므로 영수의 답들에는 모순이 없다.

민혁이의 물음들과 각각의 물음에 대한 영수의 답이 입력으로 주어질 때 영수가 생각하고 있을 가능성이 있는 답의 총 개수를 출력하는 프로그램을 작성하시오.

입력

첫째 줄에는 민혁이가 영수에게 몇 번이나 질문을 했는지를 나타내는 1 이상 100 이하의 자연수 N이 주어진다. 이어지는 N개의 줄에는 각 줄마다 민혁이가 질문한 세 자리 수와 영수가 답한 스트라이크 개수를 나타내는 정수와 볼의 개수를 나타내는 정수, 이렇게 총 세 개의 정수가 빈칸을 사이에 두고 주어진다.

출력

첫 줄에 영수가 생각하고 있을 가능성이 있는 답의 총 개수를 출력한다.

예제 입력 1 

4
123 1 1
356 1 0
327 2 0
489 0 1

예제 출력 1 

2
 

 

 


접근 방법

완전 탐색으로 접근했다. 

답이 될 수 있는 숫자 조건은 000 ~ 999 중에 아래 두 조건을 만족해야 한다.  만족하지 않으면 배열 값을 -1 로 표시한다. 

1) 모두 다른 숫자로 구성되어 있어야 함

2) 숫자에 0이 들어가면 안됨

 

그 후 반복문을 돌면서 스트라이크, 볼 갯수를 카운트하고

카운트 한 스트라이크, 볼 갯수가 처음에 입력한 스트라이크/볼 수와 일치하면

그 인덱스의 배열 값을 +1 한다. (ex. 처음 입력한 숫자가 123 1 1 이고, 비교 대상이 324이면 1strike, 1ball을 만족하므로 arr[324]++)

 

그리고 마지막에 arr[i]의 값이 N과 동일하면, 즉 N번을 물어봤기 때문에 그 물어본 횟수만큼 테스트를 통과했으면(스트라이크, 볼 갯수가 일치했으면) 그 i는 후보가 된다. 그 i가 몇개인지 카운트 하면 이 문제의 답을 구할 수 있다. 

 

 

 

[반례]

 

입력
2
123 0 0
456 0 0


정답
6

import java.util.*;

public class BOJ_2503_숫자야구 {

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int N = sc.nextInt();
        int ans = 0;

//        Integer[] arr = new Integer[1000];
        int[] arr = new int[1000];
        for (int i = 123; i <= 987; i++) {  //서로 다른 숫자 세개로 구성하므로
            String str = Integer.toString(i);   //각 자리수 비교하기 위해 형변환

            if (str.charAt(0) == str.charAt(1) || str.charAt(0) == str.charAt(2) || str.charAt(1) == str.charAt(2)
                ||str.charAt(0)=='0' || str.charAt(1)=='0' ||str.charAt(2)=='0') {  //서로 다른 숫자로 구성되지 않았으면 -1로 지정
                arr[i] = -1;
            }
        }
        //ArrayList<String> strNumList = new ArrayList<>();
        String strNum;
        //ArrayList<Integer> strikeList = new ArrayList<>();
        //ArrayList<Integer> ballList = new ArrayList<>();
        int strike;
        int ball;
        for (int i = 1; i <= N; i++) {       //N : 민혁이가 영수에게 질문한 횟수
            strNum = sc.next();
            //strNumList.add(strNum);
            strike = sc.nextInt();
            //strikeList.add(strike);
            ball = sc.nextInt();
            //ballList.add(ball);

            int strikeCnt = 0;
            int ballCnt = 0;

            for (int idx = 123; idx <= 987; idx++) {    //반복문 돌면서 strike, ball 검사
                if (arr[idx] == -1) continue;
                //System.out.print(arr[idx] + " ");
                int passCnt = 0;
                //strike 검사
                strikeCnt = 0;
                String strIdx = Integer.toString(idx);
                for (int j = 0; j < 3; j++) {
                    if (strNum.charAt(j) == strIdx.charAt(j)) strikeCnt++;
                }

                //strike 수는 맞았으니 Ball 검사
                ballCnt = 0;
                for (int p = 0; p < 3; p++) {
                    for (int q = 0; q < 3; q++) {
                        if ((strNum.charAt(p) == strIdx.charAt(q)) && (p != q)) {
                            ballCnt++;
                        }
                    }
                }
                if ((strike != strikeCnt) || ball != ballCnt) {
                    arr[idx] = -1;
                    continue;
                }

				//통과된 횟수 카운트
                if ((strike == strikeCnt) && (ball == ballCnt)) {
                    arr[idx]++;
                }
            }

        }

        for (int i = 123; i <= 987; i++) {

            if (arr[i] != -1 && arr[i] == N) {	//물어본 횟수만큼 다 만족했으면 그 숫자는 답
                ans++;
               // System.out.println(i);
            }
        }
        System.out.println(ans);

    }
}

728x90
728x90

문제 링크 : https://www.acmicpc.net/problem/15591

 

15591번: MooTube (Silver)

농부 존은 1번 동영상과 2번 동영상이 USADO 3을 가지고, 2번 동영상과 3번 동영상이 USADO 2를 가지고, 2번 동영상과 4번 동영상이 USADO 4를 가진다고 했다. 이것에 기반해서 1번 동영상과 3번 동영상의

www.acmicpc.net

 

문제

농부 존은 남는 시간에 MooTube라 불리는 동영상 공유 서비스를 만들었다. MooTube에서 농부 존의 소들은 재밌는 동영상들을 서로 공유할 수 있다. 소들은 MooTube에 1부터 N까지 번호가 붙여진 N (1 ≤ N ≤ 5,000)개의 동영상을 이미 올려 놓았다. 하지만, 존은 아직 어떻게 하면 소들이 그들이 좋아할 만한 새 동영상을 찾을 수 있을지 괜찮은 방법을 떠올리지 못했다.

농부 존은 모든 MooTube 동영상에 대해 “연관 동영상” 리스트를 만들기로 했다. 이렇게 하면 소들은 지금 보고 있는 동영상과 연관성이 높은 동영상을 추천 받을 수 있을 것이다.

존은 두 동영상이 서로 얼마나 가까운 지를 측정하는 단위인 “USADO”를 만들었다. 존은 N-1개의 동영상 쌍을 골라서 직접 두 쌍의 USADO를 계산했다. 그 다음에 존은 이 동영상들을 네트워크 구조로 바꿔서, 각 동영상을 정점으로 나타내기로 했다. 또 존은 동영상들의 연결 구조를 서로 연결되어 있는 N-1개의 동영상 쌍으로 나타내었다. 좀 더 쉽게 말해서, 존은 N-1개의 동영상 쌍을 골라서 어떤 동영상에서 다른 동영상으로 가는 경로가 반드시 하나 존재하도록 했다. 존은 임의의 두 쌍 사이의 동영상의 USADO를 그 경로의 모든 연결들의 USADO 중 최솟값으로 하기로 했다.

존은 어떤 주어진 MooTube 동영상에 대해, 값 K를 정해서 그 동영상과 USADO가 K 이상인 모든 동영상이 추천되도록 할 것이다. 하지만 존은 너무 많은 동영상이 추천되면 소들이 일하는 것이 방해될까 봐 걱정하고 있다! 그래서 그는 K를 적절한 값으로 결정하려고 한다. 농부 존은 어떤 K 값에 대한 추천 동영상의 개수를 묻는 질문 여러 개에 당신이 대답해주기를 바란다.

입력

입력의 첫 번째 줄에는 N과 Q가 주어진다. (1 ≤ Q ≤ 5,000)

다음 N-1개의 줄에는 농부 존이 직접 잰 두 동영상 쌍의 USADO가 한 줄에 하나씩 주어진다. 각 줄은 세 정수 pi, qi, ri (1 ≤ pi, qi ≤ N, 1 ≤ ri ≤ 1,000,000,000)를 포함하는데, 이는 동영상 pi와 qi가 USADO ri로 서로 연결되어 있음을 뜻한다.

다음 Q개의 줄에는 농부 존의 Q개의 질문이 주어진다. 각 줄은 두 정수 ki와 vi(1 ≤ ki ≤ 1,000,000,000, 1 ≤ vi ≤ N)을 포함하는데, 이는 존의 i번째 질문이 만약 K = ki라면 동영상 vi를 보고 있는 소들에게 몇 개의 동영상이 추천될 지 묻는 것이라는 것을 뜻한다.

 

출력

Q개의 줄을 출력한다. i번째 줄에는 농부 존의 i번째 질문에 대한 답변이 출력되어야 한다.

예제 입력 1 

4 3
1 2 3
2 3 2
2 4 4
1 2
4 1
3 1

예제 출력 1 

3
0
2

힌트

농부 존은 1번 동영상과 2번 동영상이 USADO 3을 가지고, 2번 동영상과 3번 동영상이 USADO 2를 가지고, 2번 동영상과 4번 동영상이 USADO 4를 가진다고 했다. 이것에 기반해서 1번 동영상과 3번 동영상의 USADO는 min(3,2)=2가 되고, 1번 동영상과 4번 동영상의 USADO는 min(3,4)=3이 되고, 3번 동영상과 4번 동영상의 USADO는 min(2,4)=2가 된다.

농부 존은 K=1일 때 2번 동영상, K=3일 때 1번 동영상, K=4일 때 1번 동영상을 보면 각각 몇 개의 동영상이 추천될까 궁금해하고 있다. K=1일 때 2번 동영상에서 추천되는 동영상은 1, 3, 4번 동영상이다. K=4일 때 1번 동영상으로부터 추천되는 동영상은 없다. 그러나 K=3일때는 1번 동영상에서 2번 동영상과 4번 동영상이 추천된다.

 

 


접근 방법

처음에는 노드간 모든 pair에 대해, a->b 노드로 가는 edge의 min을 구해서 a, b 노드 간의 usado를 처음부터 다 구해놓으려고 했었다. 

이 방법은 너무 비효율적일 것 같아서 각 Question마다 주어지는 k와 v에 대해서만 확인해서 그때그때 답을 구하는 것이 좋을것 같았다. 

 

그러기 위해 각각 연결된 노드들의 정보들만 저장하는 리스트 graphList를 생성했다. 

graphList[1]에는 1번 노드와 연결된 모든 노드와, 그 노드까지의 edge 정보를 저장해놓는다. (그 정보는 Node 객체에 넣어서 저장한다)

위 예제로 예시를 들면 graphList에 담긴 정보는 아래와 같다. 

 

graphList[1] => (2,3)

graphList[2] => (1,3), (3,2), (4,4)

graphList[3] => (2, 2)

graphList[4] => (2, 4)

 

 

그래서 매 Question마다 bfs를 도는데, graphList[현재노드] 의 크기만큼 돌게 되며(시작 노드와 다이렉트로 연결된 노드 모두 방문해가면서), 다이렉트로 연결되지 않은 노드에 대해서도 que.add를 통해 탐색 대상에 넣어 탐색을 하게 된다. 

 

 

import java.util.*;
public class BOJ_15591_MoonTube {
    static class Node{
        int node, weight;
        public Node(int n, int w){
            this.node = n;
            this.weight = w;
        }
    }

    static int bfs(int k, int v, ArrayList<ArrayList<Node>> graphList, int N){
        int[] visited = new int[N+1]; //노드번호 1부터 ~ N까지이므로 N+1개
        int cntVideo = 0;
        Queue<Integer> que = new LinkedList<Integer>();
        que.add(v);   //시작 노드
        visited[v] = 1;

        while(!que.isEmpty()) { //방문할 노드가 없을 때까지
            int curNode = que.poll();

            for(int i = 0; i<graphList.get(curNode).size(); i++){
                int w = graphList.get(curNode).get(i).weight;   //usado
                int n = graphList.get(curNode).get(i).node;
                if(w<k || visited[n] != 0) {continue;}    //문제에서 weight가 k이상일 때만 (w>=k)물어봄, w<k인 케이스는 패스

                que.add(n);     //다음 방문할 노드 저장. v노드와 다이렉트로 연결되지 않은 노드에 대해서도 탐색 가능 
                visited[n] = 1;
                cntVideo++;

            }
        }
        return cntVideo;
    }

    public static void main(String args[]){
        Scanner sc = new Scanner(System.in);
        int N = sc.nextInt();
        int Q = sc.nextInt();
        ArrayList<ArrayList<Node>> graphList = new ArrayList<ArrayList<Node>>();    //graphList[x]에는 x 노드와 연결된 노드의 정보와 간선 정보가 객체로 들어있다.
        for(int i = 0; i<=N; i++){//노드 1~N까지 있으므로
            graphList.add(new ArrayList<Node>());
        }
        for(int i = 1; i<=N-1; i++){
            int p = sc.nextInt();
            int q = sc.nextInt();
            int r = sc.nextInt();
            //그래프 정보 입력. 간선에 연결된 노드 양쪽에 대해 각각 정보 입력
            graphList.get(p).add(new Node(q,r));
            graphList.get(q).add(new Node(p,r));
        }
        ArrayList<Integer> ansList = new ArrayList<Integer>();
        for(int i = 1; i<=Q; i++){
            int k = sc.nextInt();
            int v = sc.nextInt();
            int ans = bfs(k, v, graphList, N);
            ansList.add(ans);
        }
        for(int i = 0; i<ansList.size(); i++){
            System.out.println(ansList.get(i));
        }



    }
}

 

 

 

 

참고 : https://fjvbn2003.tistory.com/873

 

728x90
728x90

문제 링크 : https://www.acmicpc.net/problem/1484

 

1484번: 다이어트

성원이는 다이어트를 시도중이다. 성원이는 정말 정말 무겁기 때문에, 저울이 부셔졌다. 성원이의 힘겨운 다이어트 시도를 보고만 있던 엔토피아는 성원이에게 새로운 저울을 선물해 주었다.

www.acmicpc.net

 

문제

성원이는 다이어트를 시도중이다. 성원이는 정말 정말 무겁기 때문에, 저울이 부셔졌다. 성원이의 힘겨운 다이어트 시도를 보고만 있던 엔토피아는 성원이에게 새로운 저울을 선물해 주었다. 성원이는 엔토피아가 선물해준 저울 위에 올라갔다. “안돼!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! G 킬로그램이나 더 쪘어ㅜㅠ”라고 성원이가 말했다. 여기서 말하는 G킬로그램은 성원이의 현재 몸무게의 제곱에서 성원이가 기억하고 있던 몸무게의 제곱을 뺀 것이다.

성원이의 현재 몸무게로 가능한 것을 모두 출력하는 프로그램을 작성하시오.

입력

첫째 줄에 G가 주어진다. G는 100,000보다 작거나 같은 자연수이다.

출력

첫째 줄부터 한 줄에 하나씩 가능한 성원이의 현재 몸무게를 오름차순으로 출력한다. 가능한 몸무게가 없을 때는 -1을 출력한다. 현재 몸무게는 자연수로 떨어지지 않을 수도 있는데, 이런 경우는 제외해야 한다.

예제 입력 1 

15

예제 출력 1 

4
8
 

접근 방법

이 문제는 보통 투포인터로 많이 푸는 문제이다. 즉, G = (현재+기억)*(현재-기억) 인 점을 활용하여 현재 몸무게와 기억하는 몸무게 간의 관계를 바탕으로 정해진 범위 내에서 몸무게 2개를 조절해가면서(투포인터) 수식을 만족하는 현재 몸무게를 찾는 방식이다. 

 

나는 G = (현재+기억)*(현재-기억) 에서 

  • a = 현재+기억
  • b = 현재-기억

a+b  = 2*(현재) 이므로 a+b는 짝수

인 점을 활용했다. 

 

탐색 범위는 a가 1부터(현재, 기억 모두 자연수이므로 2부터 해도 됨) G까지 했다.

G까지 한 이유는 다음과 같다.

현재와 기억의 최소 차이를 생각해봤을 때 b = 현재-기억 은 양수이므로 현재와 기억 몸무게의 최소 차이는 1이다. 이 경우를 조건의 끝이라고 생각하면 G = a가 된다. 

 

추가로

1) b = G/a인 점

2) a와 b 모두 양수인 점(a와 b를 곱해서 G가 나와야하며 G는 자연수이므로)

3) 현재 몸무게가 자연수이고, 기억하는 몸무게도 자연수인 점(13번째 line에서 a<=b가 아닌 a<b로 하면 오답으로 나온다. 즉 a>=b인 경우를 고려하면 틀린다는 소리이며 그 중 a=b인 경우가 오답의 원인이 되는 것이다. 아래 링크도 추가 참고하면 기억하는 몸무게도 자연수로 고려해야하는 것 같다.)

 

https://www.acmicpc.net/board/view/115572

 

글 읽기 - 문제 내용 추가 요청입니다.

댓글을 작성하려면 로그인해야 합니다.

www.acmicpc.net

 

 

아래 반례가 도움이 되었다. 

https://www.acmicpc.net/board/view/99783

 

글 읽기 - 1484. 다이어트 질문입니다.

댓글을 작성하려면 로그인해야 합니다.

www.acmicpc.net

import java.util.*;

public class BOJ_1484_다이어트 {

    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        TreeSet<Integer> set = new TreeSet<Integer>();

        int G = sc.nextInt();
        for(int a = 1; a<=G; a++){	//a 탐색 범위를 1부터 G까지 해야함.
            if(G%a != 0) continue;		//b가 G의 약수가 아니면 패스
            int b = G / a;				//b는 G의 약수 
            if(((a+b) % 2 != 0) || (a<=b)) continue;	//짝수가 아니거나 범위 벗어나면 패스
            set.add((a+b)/2);
        }
        if(set.size() == 0){
            System.out.println(-1);
        }

        else{
            Iterator iter = set.iterator();
            while(iter.hasNext()){
                System.out.println(iter.next());
            }
        }
    }
}

 

728x90

+ Recent posts