はじめに
初めて4完したコンテストですね。懐かしい。
なお、コードは当時提出したものと簡単に書き直したものの二つを載せます。
では、見ていきましょう。
A - Last Letter
問題文はこちら
そのままですね。
0-indexedであることに注意しましょう。
import java.io.*;
class Main{
public static void main(String[] args)throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
//Nは使わない
String decoy = br.readLine();
//Sの受け取り
String str = br.readLine();
//末尾だけ切り出して出力
System.out.println(str.substring(str.length()-1));
}
}
書き直すならこんな感じですかね。
import java.util.Scanner;
class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
//N、Sの受け取り
int N = sc.nextInt();
String S = sc.next();
//末尾の文字を出力
System.out.println(S.charAt(N-1));
}
}
charAtで一文字だけ取り出せるので使ってみました。
B - Go Straight and Turn Right
問題文はこちら
シミュレーションをしました。
今の向きを表す変数を持っておいて、Rの度に+1して90度回転するようにしました。
import java.io.*;
//文字列を一文字ずつ区切って受け取る用
class subMain{
public static String[] parStr(String someStr){
String[] str = someStr.split("");
return str;
}
}
class Main{
public static void main(String[] args)throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
//Nは必要無い
String decoy = br.readLine();
//Tの受け取り
String[] str = subMain.parStr(br.readLine());
//向きを表す変数
int to = 0;
//現在位置を表す変数
int x = 0;
int y = 0;
//順に見ていく
for(int i=0;i<str.length;i++){
//Sの時はその方向に合わせて移動
if(str[i].equals("S")){
switch(to){
case 0:
x++;
break;
case 1:
y--;
break;
case 2:
x--;
break;
case 3:
y++;
break;
//不必要だけど念のため
default:
break;
}
}
//Rの時は方向転換
else{
to = (to+1) % 4;
}
}
//出力
System.out.println(x + " " + y);
}
}
やっぱりちょっと長ったらしいので書き換えます。
import java.util.Scanner;
class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
//N、Tの受け取り
int N = sc.nextInt();
char[] T = sc.next().toCharArray();
//向きと位置を表す変数
int s=0,x=0,y=0;
//順に見ていく
for(int i=0;i<N;i++){
//Sの時
if(T[i]=='S'){
if(s==0)x++;
if(s==1)y--;
if(s==2)x--;
if(s==3)y++;
}
//Rの時
else
s = (s+1)%4;
}
//出力
System.out.println(x+" "+y);
}
}
TはString[]よりchar[]の方が扱いやすそうなのでこのように実装しました。
C - Yamanote Line Game
問題文はこちら
奇数個の整数をお互いに言うだけなので、当然ですが先攻の高橋君が勝ちます。
ですので、言ったか言ってないかを記録するboolean型配列を見ながら1から順に言っていけばACが取れます。
なお、System.outはデフォルトでオートフラッシュが有効ですので、フラッシュしてなくてTLEというのは気にする必要がありません。
import java.io.*;
class Main{
public static void main(String[] args)throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
//Nの受け取り
int N = Integer.parseInt(br.readLine());
//使ったか管理する変数
boolean[] ans = new boolean[2*N+1];
//全部trueに
for(int i=0;i<ans.length;i++){
ans[i] = true;
}
//終了までずっと続ける
while(true){
//答える数値を保持する変数
int temp = -1;
for(int i=0;i<ans.length;i++){
//まだ言ってない?
if(ans[i]){
temp = i;
ans[i] = false;
break;
}
}
//無いとは思うけど、言ってないのが見つかってない時用
if(temp==-1)
System.exit(0);
//答えの出力
System.out.println(temp+1);
//相手の答えの受け取り
temp = Integer.parseInt(br.readLine());
//oなら終了
if(temp==0)
System.exit(0);
//記録
ans[temp-1] = false;
}
}
}
特に書き直さなくて良いかなとは思いますが、書くならこんな感じでしょうか。
import java.util.Scanner;
class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
//Nの受け取り(後々楽なのでここで2倍+2する)
int N = sc.nextInt()*2+2;
//使ったかどうか管理する配列(1-indexedとして使う)
boolean[] isUsed = new boolean[N];
//1~2N+1まで見る
for(int i=1;i<N;i++){
//すでに相手が使ってる?
if(isUsed[i])
continue;
//使ってないなら出力
//なお、自分は今の数字以下を使用しないのでisUsed[i]をtrueにする必要は無い
System.out.println(i);
//相手の数字の受け取り
int num = sc.nextInt();
//0が返ってきたのでiより大きい数字は全てtrueであって
//わざわざ終了する必要は無いが、念のため
if(num==0)
break;
//相手が使った数字を記録
isUsed[num] = true;
}
}
}
まぁこれで十分ですね。
D - Swap Hats
問題文はこちら
$10^{18}$回も帽子を入れ替えるとなるとシミュレーションでは当然終わりそうにありません。ではどう考えれば良いでしょうか。
一度初期状態から揃えたい順番に並べ替えてみましょう。そのときの回数を$K$回とすると、残りの回数は$10^{18}-K$となります。
ここで、残りの回数がどう消費されていくかを考えてみましょう。すると、いずれかの二人の帽子を入れ替え続けるという方法が浮かびます。この行為は最初揃っている状態から入れ替えて、また元の揃っている状態に戻るわけですから合計偶数回でないとちょうど揃った状態では終われません。
ということで、$10^{18}-K$が偶数、すなわち$K$が偶数であれば良いのです。
import java.io.*;
//空白区切りで文字列を受け取る用
class subMain{
public static String[] parStrWithS(String someStr){
String[] str = someStr.split(" ");
return str;
}
}
class Main{
public static void main(String[] args)throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
//SとTの受け取り
String[] start = subMain.parStrWithS(br.readLine());
String[] finish = subMain.parStrWithS(br.readLine());
//一個目が一致している?
if(start[0].equals(finish[0])){
//更に2個目が一致している=初期状態で全て揃ってるのでYes
if(start[1].equals(finish[1])){
System.out.println("Yes");
System.exit(0);
}
//2個目が揃ってないなら1回、すなわち奇数回なのでNo
else{
System.out.println("No");
System.exit(0);
}
}
//1個目が揃ってない時
else{
//とりあえず揃えてみる
if(start[1].equals(finish[0])){
String temp = start[1];
start[1] = start[0];
start[0] = temp;
}
else{
String temp = start[2];
start[2] = start[0];
start[0] = temp;
}
}
//1個目を揃えた後に2個目が揃っている=1回で全部揃うのでNo
if(start[1].equals(finish[1])){
System.out.println("No");
System.exit(0);
}
//2個目が揃ってない=2回で揃うのでYes
System.out.println("Yes");
}
}
ちょっと汚いので書き換えます。
import java.util.Scanner;
class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
//各文字の受け取り
String S1 = sc.next();
String S2 = sc.next();
String S3 = sc.next();
String T1 = sc.next();
String T2 = sc.next();
String T3 = sc.next();
//揃っていない数を数える変数
int count = 0;
//それぞれ揃ってなければ加算
if(!S1.equals(T1))count++;
if(!S2.equals(T2))count++;
if(!S3.equals(T3))count++;
//二つが入れ替わっている=1回で揃うのでNo
//他は0回か2回しかないのでYes
System.out.println(count!=2?"Yes":"No");
}
}
文字はどれも一文字で空白区切りだとわかっているのでchar[]で受け取っても良いかもしれません。
感想
A:簡単
B:まぁまぁ易しい
C:インタラクティブ問題だからといって身構える必要は無い問題だった
D:気付けば簡単
って感じでした。
普段のABCもこれくらい易しいと助かるんですが・・・。