1. 출제자가 의도한 풀이는 이분매칭

2. 이 문제를 보고 감이 안와서 질문들을 보고 해결

3. min, max 범위를 계속 구하고

4. 마지막에 min > max + 앱실론 으로 확인

5. 실수 연산에는 앱실론을 앞으로 거의 계속 사용하자.

import java.util.*;
import java.io.*;
/**
* https://www.acmicpc.net/problem/14488
* BOJ 백준온라인져지 14488 준오는 급식충이야!! 풀이
*/
public class Main {
private static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
public static void main (String args[]) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String str1[] = br.readLine().split(" ");
int N = Integer.parseInt(str1[0]);
double T = Double.parseDouble(str1[1]);
long position[] = new long[N];
String str2[] = br.readLine().split(" ");
for (int i = 0; i < N; i++) {
position[i] = Long.parseLong(str2[i]);
}
double min = -1000000000 * 1200000000;
double max = 1000000000 * 1200000000;
String str3[] = br.readLine().split(" ");
for (int i = 0; i < N; i++) {
int velocity = Integer.parseInt(str3[i]);
min = Math.max(min, velocity * -T + position[i]);
max = Math.min(max, velocity * T + position[i]);
}
if (min > max + 1e-04) bw.write("0");
else bw.write("1");
bw.flush();
}
}
view raw Main.java hosted with ❤ by GitHub

문제

심술쟁이 해커 임준오(동탄 주민)는 오늘도 점심시간을 기다리고 있다. 준오와 친구들은 매일 복도 어딘가의 한 지점에 모여서 함께 밥을 먹으러 간다. 선린의 복도는 직선형으로 되어있고, 준오와 친구들은 이 복도 어딘가에 위치한 교실에서 종이 치기만을 기다리고 있다.

‘띵~ 디딩~ 띵디딩디딩~’

종이 울렸다! 준오와 친구들은 최대한 빨리 한 지점에서 만나야한다. 그렇지 않으면 홍수처럼 쏟아지는 학생들에 휩쓸려 제각각 급식실로 떠내려갈지도 모른다.

준오를 포함한 친구들의 교실 위치 xi와 각 학생들의 달리기 속도 vi, 그리고 홍수가 밀려오기까지 남은 시간 T가 주어진다. 과연 준오와 친구들은 함께 밥을 먹으러 갈 수 있을까?

교실은 1차원 직선 위 어딘가에 위치해있다. 학생들의 달리기 속도는 항상 일정하며, 모든 학생들이 종이 울림과 동시에 뛰어나온다. 홍수가 터지는 시점과 친구들이 만나는 시점이 일치한다면 홍수에 떠내려가기 전에 만날 수 있는 것으로 간주한다.

입력

첫째 줄에는 준오를 포함한 친구들의 수 N과 홍수까지 남은 시간 T가 주어진다. (1 ≤ N ≤ 50,000, 1 ≤ T(초) ≤ 1,000,000,000) 남은 시간 T는 소숫점 넷째자리의 실수로 주어진다.

둘째 줄에는 N명 학생들의 위치 x1, x2, ..., xn(1 ≤ xi ≤ 1,000,000,000)가 주어진다. (자연수, 미터 단위)

셋째 줄에는 N명 학생들의 속도 v1, v2, ..., vn(1 ≤ vi ≤ 1,000,000,000)가 주어진다. (자연수, 초당 미터)

출력

준오와 친구들이 모두 만날 수 있으면 1을, 그렇지 않으면 0을 출력한다.


1. 최소공배수 = A * B / 최대공약수

2. 오버플로우를 조심해라

import java.util.*;
import java.io.*;
/**
* https://www.acmicpc.net/problem/5347
* BOJ 백준온라인져지 5347 LCM 풀이
*/
public class Main {
private static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
public static void main (String args[]) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int N = Integer.parseInt(br.readLine());
for (int i = 0; i < N; i++) {
String str1[] = br.readLine().split(" ");
Long A = Long.parseLong(str1[0]);
Long B = Long.parseLong(str1[1]);
bw.write((A * B / gcm(A, B)) + "\n");
}
bw.flush();
}
private static long gcm (long a, long b) {
long mod;
while ((mod = a % b) > 0) {
a = b;
b = mod;
mod = a % b;
}
return b;
}
}
view raw Main.java hosted with ❤ by GitHub

문제

두 수 a와 b가 주어졌을 때, a와 b의 최소 공배수를 구하는 프로그램을 작성하시오.

입력

첫째 줄에 테스트 케이스의 개수 n이 주어진다. 다음 n개 줄에는 a와 b가 주어진다. a와 b사이에는 공백이 하나 이상 있다. 두 수는 백만보다 작거나 같은 자연수이다.

출력

각 테스트 케이스에 대해서 입력으로 주어진 두 수의 최소공배수를 출력한다.


1. 1 ~ (1 << N) - 1 까지 구해서 했었는데, String 으로 변환하는 과정에서 에러가 났다.

2. 저 방법으로는 풀 수 없는 문제 같아서 규칙을 찾아보니

3. 1 1

4. 2 110

5. 3 11100

6. 4 1111000

7. 0 의 개수가 N - 1인 이유는 N 자리의 전에는 1이 겹치기 때문에 + 돼서 올림됨.

8. 3 일 경우로 보면 001 010 011 100 101 110 111 겹치는걸 볼 수 있다.

import java.util.*;
import java.io.*;
/**
* https://www.acmicpc.net/problem/8741
* BOJ 백준온라인져지 8741 이진수 풀이
*/
public class Main {
private static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
public static void main (String args[]) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int N = Integer.parseInt(br.readLine());
for (int i = 0; i < N; i++) bw.write("1");
for (int i = 1; i < N; i++) bw.write("0");
bw.flush();
}
}
view raw Main.java hosted with ❤ by GitHub

문제

세계적인 이진수 매니아 현수는 오늘도 이진수를 연구하고 있다.

오늘은 이진수로 나타냈을 때, k자리 이하인 모든 자연수의 합을 구해보려고 한다.

k가 주어졌을 때, 이진수로 나타냈을 때, k자리 이하인 모든 자연수의 합을 구하는 프로그램을 작성하시오.

입력

첫째 줄에 k가 주어진다. (1 ≤ k ≤ 106)

출력

첫째 줄에 이진수로 나타냈을 때, k자리 이하인 모든 자연수의 합을 이진수로 출력한다.


1. a, b, c 가 0 인 경우는 비트 연산자로 확인

2. 출력은 AP 또는 GP 가 항상 맞기 때문에, 공차만 확인한다.

3. 등차수열이 아닌경우는 등비수열로 확정

import java.util.*;
import java.io.*;
/**
* https://www.acmicpc.net/problem/4880
* BOJ 백준온라인져지 4880 다음수 풀이
*/
public class Main {
private static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
public static void main (String args[]) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
while (true) {
String str1[] = br.readLine().split(" ");
int a = Integer.parseInt(str1[0]);
int b = Integer.parseInt(str1[1]);
int c = Integer.parseInt(str1[2]);
if ((a | b | c) == 0) break;
if (b - a == c - b) bw.write("AP " + (c + (c - b)));
else bw.write("GP " + (c * (c / b)));
bw.write("\n");
}
bw.flush();
}
}
view raw Main.java hosted with ❤ by GitHub

문제

등차수열(AP)은 인접한 두 수의 차이(공차)가 일정한 수열이다. 예를 들어, 3, 5, 7, 9, 11, 13, ...은 차이가 2로 일정한 등차수열이다. 이 문제에서 등차수열의 공차는 항상 0이 아닌 정수이다.

등비수열(GP)는 각 항이 그 앞과 일정한 비(공비)를 가지는 수열이다. 예를 들어, 2, 6, 18, 54, ...은 공비가 3인 등비수열이다. 이 문제에서 등비수열의 공비는 항상 0이 아닌 정수이다.

어떤 수열의 연속한 세개의 숫자가 주어졌을 때, 이 수열이 등차수열인지 등비수열인지를 알아낸 뒤, 다음 항을 구하는 프로그램을 작성하시오.

입력

입력은 여러 개의 테스트 케이스로 이루어져 있다. 각 테스트 케이스는 수열의 연속하는 세 수 a1, a2, a3이 한 줄에 주어진다. (-10,000 < a1, a2, a3 < 10,000) a1, a2, a3은 서로 같지 않다.

입력의 마지막 줄에는 0이 세 개 주어진다.

출력

각 테스트 케이스에 대해서, 등차수열이면 AP를, 등비수열이면 GP를 출력한 뒤, 다음 항을 출력한다. 모든 입력은 항상 등차수열이나 등비수열이다.


1. 1 << 0 ~ j 까지 해보면 된다. 

2. 비트연산자를 사용한다.

3. 비트 시프트 연산을 제외한 비트 연산자는 관계 연산자 (< = >) 보다 우선순위가 낮다.

4. << >> 가 <= >= < > 보다 높고 <= >= < > 보다 & ^ | 가 낮다.

5. 헷갈리지 않게 괄호를 필수로 계속 사용하면 될거같다.

import java.util.*;
import java.io.*;
/**
* https://www.acmicpc.net/problem/3460
* BOJ 백준온라인져지 3460 이진수 풀이
*/
public class Main {
private static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
public static void main (String args[]) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int N = Integer.parseInt(br.readLine());
for (int i = 0; i < N; i++) {
int n = Integer.parseInt(br.readLine());
for (int j = 0; n >= 1 << j; j++) {
if ((n & (1 << j)) >= 1) bw.write(j + " ");
}
bw.write("\n");
}
bw.flush();
}
}
view raw Main.java hosted with ❤ by GitHub

문제

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

입력

첫째 줄에 테스트 케이스의 개수 T가 주어진다. 각 테스트 케이스는 한 줄로 이루어져 있고, n이 주어진다. (1 ≤ T ≤ 10, 1 ≤ n ≤ 106)

출력

각 테스트 케이스에 대해서, 1의 위치를 공백으로 구분해서 줄 하나에 출력한다. 위치가 낮은 것부터 출력한다.


1. 단순하게 생각하면 가로로 왔다갔다, 세로로 왔다갔다.

2. 정해는 O(1) 이다.

3. 하지만 푸는 방법은 여러가지!

4. 나는 0,0 에서 시작하는걸로 생각하고 t 와 x 그리고 t 와 y 를 하나로 합쳐서 생각했다.

5.(t + x) / w / 2 의 나머지가 1이면 w 에 도착한거니까 w - (t +x) % w 반대로 생각하는 경우다.

6. y 도 마찬가지

7. 출제자의 의도는 아마 for 문을 사용해서 반복하는걸 줄일수 있느냐? 그리고 정해를 찾을 수 있느냐 2개를 확인하는거 같다.

import java.util.*;
import java.io.*;
/**
* https://www.acmicpc.net/problem/10158
* BOJ 백준온라인져지 10158 개미 풀이
*/
public class Main {
public static void main (String args[]) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
String str1[] = br.readLine().split(" ");
String str2[] = br.readLine().split(" ");
int w = Integer.parseInt(str1[0]);
int h = Integer.parseInt(str1[1]);
int x = Integer.parseInt(str2[0]);
int y = Integer.parseInt(str2[1]);
int N = Integer.parseInt(br.readLine());
boolean maxW = (x + N) / w % 2 == 1;
boolean maxH = (y + N) / h % 2 == 1;
int resultX = 0;
int resultY = 0;
if (maxW) {
resultX = w - (x + N) % w;
} else {
resultX = (x + N) % w;
}
if (maxH) {
resultY = h - (y + N) % h;
} else {
resultY = (y + N) % h;
}
bw.write(resultX + " " + resultY);
bw.flush();
}
}
view raw Main.java hosted with ❤ by GitHub

문제

가로 길이가 w이고 세로 길이가 h인 2차원 격자 공간이 있다. 이 격자는 아래 그림처럼 왼쪽 아래가 (0,0)이고 오른쪽 위가 (w,h)이다. 이 공간 안의 좌표 (p,q)에 개미 한 마리가 놓여있다. 개미는 오른쪽 위 45도 방향으로 일정한 속력으로 움직이기 시작한다. 처음에 (p,q)에서 출발한 개미는 1시간 후에는 (p+1,q+1)로 옮겨간다. 단, 이 속력으로 움직이다가 경계면에 부딪치면 같은 속력으로 반사되어 움직인다.

위 그림은 6×4 격자에서 처음에 (4,1)에서 출발한 개미가 움직인 길을 보여주고 있다. 처음에 (4,1)에 있는 개미는 2시간 후에 (6,3)에 있으며 8시간 후에 (0,1)에 있다. 만일 그 개미가 처음에 (5,3)에 있었다면 매 시간마다 (6,4), (5,3), (4,2), (3,1)로 움직인다. 

여러분은 크기 w×h인 격자 공간에서 처음에 (p,q)에서 출발하는 개미의 t시간 후의 위치 (x,y)를 계산하여 출력해야 한다. 개미는 절대 지치지 않고 같은 속력으로 이동한다고 가정한다. 

문제에서 w와 h는 자연수이며 범위는 2 ≤ w,h ≤ 40,000이다. 그리고 개미의 초기 위치 p와 q도 자연수이며 범위는 각각 0 < p < w과 0 < q < h이다. 그리고 계산할 시간 t의 범위는 1 ≤ t ≤ 200,000,000이다. 

입력

첫줄에는 w와 h가 공백을 사이에 두고 주어진다. 그 다음 줄에는 초기 위치의 좌표값 p와 q가 공백을 사이에 두고 주어진다. 3번째 줄에는 개미가 움직일 시간 t가 주어진다. 

출력

출력은 t 시간 후에 개미의 위치 좌표 (x,y)의 값 x와 y를 공백을 사이에 두고 출력한다. 


1. 구하면 바로 출력하고 종료

2. 못구하면 0 출력

import java.util.*;
import java.io.*;
/**
* https://www.acmicpc.net/problem/2501
* BOJ 백준온라인져지 2501 약수 구하기 풀이
*/
public class Main {
public static void main (String args[]) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
String str1[] = br.readLine().split(" ");
int N = Integer.parseInt(str1[0]);
int K = Integer.parseInt(str1[1]);
for (int i = 1; i <= N; i++) {
if (N % i == 0) {
K--;
if (K == 0) {
System.out.println(i);
return;
}
}
}
bw.write("0");
bw.flush();
}
}
view raw Main.java hosted with ❤ by GitHub

문제

어떤 자연수 p와 q가 있을 때, 만일 p를 q로 나누었을 때 나머지가 0이면 q는 p의 약수이다. 

6을 예로 들면

  • 6 ÷ 1 = 6 … 0
  • 6 ÷ 2 = 3 … 0
  • 6 ÷ 3 = 2 … 0
  • 6 ÷ 4 = 1 … 2
  • 6 ÷ 5 = 1 … 1
  • 6 ÷ 6 = 1 … 0

그래서 6의 약수는 1, 2, 3, 6, 총 네 개이다.

두 개의 자연수 N과 K가 주어졌을 때, N의 약수들 중 K번째로 작은 수를 출력하는 프로그램을 작성하시오.

입력

첫째 줄에 N과 K가 빈칸을 사이에 두고 주어진다. N은 1 이상 10,000 이하이다. K는 1 이상 N 이하이다.

출력

첫째 줄에 N의 약수들 중 K번째로 작은 수를 출력한다. 만일 N의 약수의 개수가 K개보다 적어서 K번째 약수가 존재하지 않을 경우에는 0을 출력하시오.


1. 홀수들은 n mod 2 > 0 

import java.util.*;
import java.io.*;
/**
* https://www.acmicpc.net/problem/2576
* BOJ 백준온라인져지 2576 홀수 풀이
*/
public class Main {
public static void main (String args[]) throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
int min = Integer.MAX_VALUE;
int result = 0;
for (int i = 0; i < 7; i++) {
int number = Integer.parseInt(br.readLine());
if (number % 2 == 1) {
result += number;
if (min > number) min = number;
}
}
if (result == 0) {
System.out.println(-1);
return;
}
bw.write(result + "\n");
bw.write(String.valueOf(min));
bw.flush();
}
}
view raw Main.java hosted with ❤ by GitHub

문제

7개의 자연수가 주어질 때, 이들 중 홀수인 자연수들을 모두 골라 그 합을 구하고, 고른 홀수들 중 최소값을 찾는 프로그램을 작성하시오.

예를 들어, 7개의 자연수 12, 77, 38, 41, 53, 92, 85가 주어지면 이들 중 홀수는 77, 41, 53, 85이므로 그 합은

77 + 41 + 53 + 85 = 256

이 되고,

41 < 53 < 77 < 85

이므로 홀수들 중 최소값은 41이 된다.

입력

입력의 첫째 줄부터 일곱 번째 줄까지 한 줄에 하나의 자연수가 주어진다. 주어지는 자연수는 100보다 작다.

출력

홀수가 존재하지 않는 경우에는 첫째 줄에 -1을 출력한다. 홀수가 존재하는 경우 첫째 줄에 홀수들의 합을 출력하고, 둘째 줄에 홀수들 중 최소값을 출력한다.


1. 자기자신을 제외한 약수의 최대값은 N / 2

2. 뭔가 값이 적을거라 생각되고 StringBuilder 같은거 사용안함.

3. 성공

import java.util.*;
import java.io.*;
/**
* https://www.acmicpc.net/problem/9506
* BOJ 백준온라인져지 9506 약수들의 합 풀이
*/
public class Main {
public static void main (String args[]) throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
while (true) {
int N = Integer.parseInt(br.readLine());
if (N == -1) break;
ArrayList<Integer> list = new ArrayList<>();
for (int i = 1, temp = N / 2 + 1; i <= temp; i++) {
if (N % i == 0) {
list.add(i);
}
}
String str = "";
int tempN = N;
for (int i = 0, size = list.size(); i < size; i++) {
int n = list.get(i);
tempN -= n;
str += n;
if (i + 1 < size) {
str += " + ";
}
}
bw.write(N + " ");
if (tempN == 0) bw.write("= " + str);
else bw.write("is NOT perfect.");
bw.write("\n");
}
bw.flush();
}
}
view raw Main.java hosted with ❤ by GitHub

문제

어떤 숫자 n이 자신을 제외한 약수들의 합으로 나타내어 지면, 그 수를 완벽한 수라고 한다. 

예를 들어 6은 6 = 1 + 2 + 3 으로 완벽한 수이다.

n이 완벽한 수 인지 아닌지 판단해주는 프로그램을 작성하라.

입력

입력은 테스트 케이스마다 한 줄 간격으로 n이 주어진다. (2 < n < 100, 000)

입력의 마지막엔 -1이 주어진다.

출력

테스트케이스 마다 한줄에 하나씩 출력해야 한다.

n이 완벽한 수라면, n을 n이 아닌 약수들의 합으로 나타내어 출력한다(예제 출력 참고).

이 때, 약수들은 오름차순으로 나열해야 한다.

n이 완벽한 수가 아니라면 n is NOT perfect. 를 출력한다.


1. 시뮬레이션.

2. 막대기 반을 버리니까 result--

3. 더 깔끔하게 하고 싶으면 else 일 경우에만 result++ 해주면될듯

import java.util.*;
import java.io.*;
/**
* https://www.acmicpc.net/problem/1094
* BOJ 백준온라인져지 1094 막대기 풀이
*/
public class Main {
public static void main (String args[]) throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
int min = 64;
int cur = min;
int X = Integer.parseInt(br.readLine());
int result = 1;
while (cur != X) {
min = min / 2;
if (X <= cur - min) {
cur -= min;
result--;
}
result++;
}
bw.write(String.valueOf(result));
// 가지고 있는 막대 중 길이가 가장 짧은 것을 절반으로 자른다.
// 만약, 위에서 자른 막대의 절반 중 하나를 버리고 남아있는 막대의 길이의 합이 X보다 크거나 같다면, 위에서 자른 막대의 절반 중 하나를 버린다.
bw.flush();
}
}
view raw Main.java hosted with ❤ by GitHub

문제

지민이는 길이가 64cm인 막대를 가지고 있다. 어느날, 그는 길이가 Xcm인 막대가 가지고 싶어졌다. 지민이는 원래 가지고 있던 막대를 더 작은 막대로 자른다음에, 풀로 붙여서 길이가 Xcm인 막대를 만드려고 한다.

막대를 자르는 가장 쉬운 방법은 절반으로 자르는 것이다. 지민이는 아래와 같은 과정을 거쳐서 막대를 자르려고 한다.

  1. 지민이가 가지고 있는 막대의 길이를 모두 더한다. 처음에는 64cm 막대 하나만 가지고 있다. 이 때, 합이 X보다 크다면, 아래와 같은 과정을 반복한다.
    1. 가지고 있는 막대 중 길이가 가장 짧은 것을 절반으로 자른다.
    2. 만약, 위에서 자른 막대의 절반 중 하나를 버리고 남아있는 막대의 길이의 합이 X보다 크거나 같다면, 위에서 자른 막대의 절반 중 하나를 버린다.
  2. 이제, 남아있는 모든 막대를 풀로 붙여서 Xcm를 만든다.

X가 주어졌을 때, 위의 과정을 거친다면, 몇 개의 막대를 풀로 붙여서 Xcm를 만들 수 있는지 구하는 프로그램을 작성하시오. 

입력

첫째 줄에 X가 주어진다. X는 64보다 작거나 같은 자연수이다.

출력

문제의 과정을 거친다면, 몇 개의 막대를 풀로 붙여서 Xcm를 만들 수 있는지 출력한다.


+ Recent posts