
문제
이번에 캬루는 소수를 배신했다. 소수의 한 자리를 바꾸어서 소수가 아니게 만들어버렸다. 구체적으로는, 0으로 시작하지 않는 N자리 소수 P에 대해 어떤 수 Q가 P-캬루라는 것은 다음을 모두 만족하는 것을 의미한다.
• Q는 2 이상의 N자리 정수이며, 0으로 시작하지 않는다.
• P와 Q의 서로 다른 자릿수는 하나뿐이다.
• Q는 소수가 아니다.
다음은 N=2, P= 19일 때 P-캬루와 P-캬루가 아닌 수의 예시이다.
• Q = 9는 1자리 정수이므로 19-캬루가 아니다. 09처럼 수가 0으로 시작할 수는 없다.
• Q = 92는 P = 19와 서로 다른 자릿수가 두 개이므로 19-캬루가 아니다.
• Q = 29는 소수이기 때문에 19-캬루가 아니다.
• Q = 16,49 등은 19-캬루이다.
N자리 소수 P가 주어졌을 때, P-캬루인 수가 적어도 N개 있다는 것을 증명할 수 있다. 이 N개의 수를 직접 찾아보자.
입력
입력 첫째 줄에 테스트 케이스의 수가 주어진다. (1 ≤ T ≤ 3545)
각 테스트 케이스는 한 줄로 이루어져 있으며, 각 줄에는 문제의 N과 P가 공백으로 구분되어 주어진다.
(1 ≤ N ≤ 100; 10^(N-1) ≤ P < 10^N; P는 소수)
주어지는 모든 N의 합은 3545 이하이다.
출력
각 테스트 케이스마다 N개의 줄을 출력한다.
i번째 줄에는 Q_i와 R_i를 공백으로 구분하여 출력한다. Q_i는 서로 다른 P-캬루들이며,
R.는 2 ≤ R_i < Q_i 인 Q_i의 약수이다.
접근
한자리 수가 다른 소수가 아닌 수와 약수를 출력해야 한다.
우선 각 배수의 특징을 알아보자
- 2의 배수 : 모든 짝수는 2의 배수
- 3의 배수 : 자릿수의 합이 3의 배수이면 해당 수는 3의 배수
- 4의 배수 : 마지막 두 자리가 00, 04, 08, 12, 16, 20, ... 등 4의 배수인 수
- 5의 배수 : 0 또는 5로 끝나는 수
- 8의 배수 : 마지막 세 자리가 000, 008, 016, 024, ... 등 8의 배수인 수
- 9의 배수 : 자릿수의 합이 9의 배수이면 해당 수는 9의 배수
- 10의 배수 : 0으로 끝나는 수
이 중 모든 자리수의 합이 3의 배수이면 3의 배수라는 성질을 이용한다.
먼저, 소수의 모든 자리수를 합쳐 3으로 나눈 나머지값(@)을 구한다.
만약 주어진 소수의 어느 자리수에서 @를 뺀다면, 모든 자리수의 합은 3의 배수가 됨으로, 이는 3의 배수이다.
따라서 각 자리수를 탐색하면서 @를 뺀 수를 대신 해당 자리수에 넣는다.
이 때, @를 뺀 값이 음수이거나 0 이라면 +3을 더해 이 값을 보정한다
(0인 경우, 맨 앞자리가 아니면 문제가 되지는 않지만, 편의상 보정한다.)
또한 1자리 수의 경우, 3은 3의 배수이긴 하나 소수이다.
따라서, 1의 자리수인 경우에만 4로 강제적으로 지정하였다.
구현
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
//https://www.acmicpc.net/problem/31288
public class 캬루 {
public static String solution(int n, String num) {
StringBuilder sb = new StringBuilder();
if(n==1) return "4 2"; //한자리 수일 경우, 3도 소수임으로 4로 고정
//모든자리숫자의 합이 3의 배수면 3의 배수임을 이용
//모든 자리 숫자의 합을 3으로 나눈 나머지 계산
int remainder = 0;
for(char c : num.toCharArray()) {
int x = c - '0';
remainder = (x+remainder)%3;
}
//각 자리수 탐색
for(int i=0;i<n;i++) {
//현재 수 - 나머지, 양수가 아닌 경우 +3을 더해 보정
int x = num.charAt(i)- '0';
int next= (x-remainder)<=0 ? (x-remainder+3) : (x-remainder);
String front = num.substring(0, i);
String back = num.length()-1>i ? num.substring(i+1) : "";
String answer = front+next+back;
sb.append(answer +" "+" 3\n");//3으로 나뉘어 지는 값 출력
}
return sb.toString().trim();
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(br.readLine());
StringBuilder sb = new StringBuilder();
StringTokenizer st;
for(int i=0;i<n;i++) {
st = new StringTokenizer(br.readLine());
int m = Integer.parseInt(st.nextToken());
String num = st.nextToken();
sb.append(solution(m, num)+"\n");
}
System.out.println(sb.toString());
br.close();
}
}
'알고리즘' 카테고리의 다른 글
[백준] 31945번: 정육면체의 네 꼭짓점 Java (0) | 2024.06.23 |
---|---|
[백준] 12789번 : 도키도키 간식드리미 Java (0) | 2023.11.05 |
[백준] 29332번: 보물 지도 JAVA (0) | 2023.09.03 |
[백준] 28682번: 재우야 임관하자 JAVA (0) | 2023.08.19 |
[백준] 28432번: 끝말잇기 JAVA (0) | 2023.08.11 |
댓글