LoginSignup
0
0

ABC319A~Eの解答[Java]

Posted at

はじめに

今回のは所用で出られなかったので後日解いたものをEまで載せようと思います。

なお、僕のライブラリは提出結果よりご確認ください。
では、見ていきましょう。

A - Legendary Players

問題文はこちら

改行を全部空白に直してsplitして全探索しました。

A.java
final class Main {

	private static final boolean autoFlush = false;
	private static final SimpleScanner sc = new SimpleScanner( System.in );
	private static final SimplePrinter out = new SimplePrinter( System.out, autoFlush );

	public static void main ( String[] args ) {

		//問題文からコピペして修正
		String[] S = "tourist 3858 ksun48 3679 Benq 3658 Um_nik 3648 apiad 3638 Stonefeang 3630 ecnerwala 3613 mnbvmar 3555 newbiedmy 3516 semiexp 3481".split(" ");
		//sの受け取り
		String s = sc.next();

		//全探索
		for(int i=0;;i++){
			if(S[i].equals(s)){
				out.println(S[i+1]);
				break;
			}
		}

		out.close();
	}
}

Java13から使用できるテキストブロックを用いれば問題文のものをコピペしてそのまま使えましたね。

A改.java
import java.util.Scanner;
class Main{
	public static void main(String[] args){

		//問題文のものをコピペ
		String[] str = """
tourist 3858
ksun48 3679
Benq 3658
Um_nik 3648
apiad 3638
Stonefeang 3630
ecnerwala 3613
mnbvmar 3555
newbiedmy 3516
semiexp 3481
""".split("[\n|\s]"); //改行と空白で区切る

		//後は前述のコードと同じ
		Scanner sc = new Scanner(System.in);
		String S = sc.next();
		for(int i=0;;i++){
			if(S.equals(str[i])){
				System.out.println(str[i+1]);
				return;
			}
		}
	}
}

どちらにせよ、ちょっとめんどくさい…。

B - Measure

問題文はこちら

問題文の通りに実装しました。

B.java
final class Main {

	private static final boolean autoFlush = false;
	private static final SimpleScanner sc = new SimpleScanner( System.in );
	private static final SimplePrinter out = new SimplePrinter( System.out, autoFlush );

	public static void main ( String[] args ) {

		//Nの受け取り
		int N = sc.nextInt();

		//問題文の通りに文字列の構築
		StringBuilder ans = new StringBuilder();
		for(int i=0;i<=N;i++){

			//数字が見つからない場合を考慮してフラグで管理
			boolean flag = false;
			for(int j=1;j<10;j++){
				if(N%j==0&&i%(N/j)==0){
					ans.append(j);
					flag = true;
					break;
				}
			}
			if(!flag)
				ans.append("-");
		}

		//構築した文字列の出力
		out.println(ans);

		out.close();
	}
}

ちょっと手間取りましたが、難しくはないですね。

C - False Hope

問題文はこちら

判定メソッドが長くなっちゃいましたが、順列全探索でがっかりしない組み合わせの数を求めてあげることで答えを求めました。

C.java
final class Main {

	private static final boolean autoFlush = false;
	private static final SimpleScanner sc = new SimpleScanner( System.in );
	private static final SimplePrinter out = new SimplePrinter( System.out, autoFlush );

	public static void main ( String[] args ) {

		//cの受け取り
		int[][] c = sc.nextInt(3,3);

		//順列用配列
		int[] map = new int[9];
		Arrays.setAll(map,i->i);

		//がっかりしない組み合わせの総数
		int count = 0;

		//順列全探索
		int[][] grid = new int[3][3];
		do{
			for(int i=0;i<9;i++)
				grid[map[i]/3][map[i]%3] = i;
			if(check(grid,c))
				count++;
		}while(ArrayFunction.nextPermutation(map));

		//答えの出力
		//(ライブラリに階乗を作ったはずだったんだけど、見当たらなくて焦って汚いコードを書いてしまった…)
		out.println((double)count/9/8/7/6/5/4/3/2);

		out.close();
	}

	//判定用メソッド(がっかりしないならtrue、がっかりするならfalse)
	private static boolean check(int[][] grid,int[][] c){
		for(int i=0;i<3;i++){
			int index1 = grid[i][0]<Math.max(grid[i][1],grid[i][2])?0:1;
			int index2 = grid[i][2]<Math.max(grid[i][0],grid[i][1])?2:1;
			if(c[i][index1]==c[i][index2])
				return false;
			index1 = grid[0][i]<Math.max(grid[1][i],grid[2][i])?0:1;
			index2 = grid[2][i]<Math.max(grid[0][i],grid[1][i])?2:1;
			if(c[index1][i]==c[index2][i])
				return false;
		}
		int index1 = grid[0][0]<Math.max(grid[1][1],grid[2][2])?0:1;
		int index2 = grid[2][2]<Math.max(grid[0][0],grid[1][1])?2:1;
		if(c[index1][index1]==c[index2][index2])
			return false;
		index1 = grid[0][2]<Math.max(grid[2][0],grid[1][1])?0:1;
		index2 = grid[2][0]<Math.max(grid[0][2],grid[1][1])?2:1;
		if(c[index1][2-index1]==c[index2][2-index2])
			return false;
		return true;
	}
}

D - Minimum Width

問題文はこちら

横幅に対して行数は広義単調減少なので、二分探索を用いて目的の横幅を求めました。

D.java
final class Main {

	private static final boolean autoFlush = false;
	private static final SimpleScanner sc = new SimpleScanner( System.in );
	private static final SimplePrinter out = new SimplePrinter( System.out, autoFlush );

	public static void main ( String[] args ) {

		//N、M、Lの受け取り
		int N = sc.nextInt();
		int M = sc.nextInt();
		int[] L = sc.nextInt(N);

		//Lの最大値以上なのは確定なので最大値を下限にする
		long a = MathFunction.max(L);
		long b = 1_000_000_000_000_000_000L;
		long ans = b;

		//二分探索
		while(a-b<1){
			long c = a+b>>1;

			//必要な行数を求める
			int count = 1;
			long now = -1;
			for(int num:L){
				if(now+1+num>c){
					count++;
					now = -1;
				}
				now += num+1;
			}

			if(count<=M)
				b = (ans=c)-1;
			else
				a = c+1;
		}

		//答えの出力
		out.println(ans);

		out.close();
	}
}

これはサクッと解けました。

E - Bus Stops

問題文はこちら

公式解説にあるとおり、840を周期として見れるので事前に$q=0~839$での答えを計算しておき、答えを求めました。

E.java
final class Main {

	private static final boolean autoFlush = false;
	private static final SimpleScanner sc = new SimpleScanner( System.in );
	private static final SimplePrinter out = new SimplePrinter( System.out, autoFlush );

	public static void main ( String[] args ) {

		//N、X、Y、P、Tの受け取り
		int N = sc.nextInt();
		int X = sc.nextInt();
		int Y = sc.nextInt();
		int[] P = new int[N-1];
		int[] T = new int[N-1];
		for(int i=0;i<N-1;i++){
			P[i] = sc.nextInt();
			T[i] = sc.nextInt();
		}

		//前計算
		long[] cost = new long[840];
		for(int i=0;i<840;i++){
			cost[i] = X+i;
			for(int j=0;j<N-1;j++)
				cost[i] = (cost[i]+P[j]-1)/P[j]*P[j]+T[j];
			cost[i] -= i;
		}

		//Qの受け取り
		int Q = sc.nextInt();

		//クエリに答える
		while(Q-->0){
			int q = sc.nextInt();
			out.println(q+cost[q%840]+Y);
		}

		out.close();
	}
}

早い段階で気づきはしましたが、実装に手こずって結局数十分かけてしまいました…。

感想

A:ちょっとめんどくさい
B,C,D:易しい
E:比較的気づきやすいかも?
って感じでした。

思ったより解きやすかったし、出たかったな…悲しい…。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0