ぶっつけ本番でやってみましたが、けっこう難しいし、Java で参戦したんですが、I/O 系のコードがめんどくさい。ちょっとテンプレートを用意してみることにしました。
テンプレートコード
public final class MainTemplate { private static void execute(final IO io) throws Exception { } public static void main(final String[] args) throws Exception { try (IO io = new IO(System.in, System.out)) { execute(io); } } public static final class IO implements AutoCloseable { private final java.io.InputStream in; private final java.io.BufferedOutputStream out; private static final int BUFFER_SIZE = 1 << 16; private final byte[] buf = new byte[BUFFER_SIZE]; private int pos = 0; private int end = 0; public IO(final java.io.InputStream in, final java.io.OutputStream out) throws java.io.IOException { this.in = in; this.out = new java.io.BufferedOutputStream(out); } @Override public void close() throws java.io.IOException { out.close(); } private int fetchByte() throws java.io.IOException { if (pos >= end) { pos = 0; end = in.read(buf); if (end <= 0) { return -1; } } return buf[pos++]; } public String nextString() throws java.io.IOException { int c; for (c = fetchByte(); c <= ' '; c = fetchByte()) { } final StringBuilder sb = new StringBuilder(); for (; c > ' '; c = fetchByte()) { sb.append((char) c); } return sb.toString(); } public String[] nextString(final int n) throws java.io.IOException { final String[] result = new String[n]; for (int i = 0; i < n; i++) { result[i] = nextString(); } return result; } public int nextInt() throws java.io.IOException { int val = 0; int c; for (c = fetchByte(); c <= ' '; c = fetchByte()) { } boolean neg = c == '-'; if (c == '-' || c == '+') { c = fetchByte(); } for (; c >= '0' && c <= '9'; c = fetchByte()) { val = (val << 3) + (val << 1) + (c & 15); } return neg ? -val : val; } public int[] nextInt(final int n) throws java.io.IOException { final int[] result = new int[n]; for (int i = 0; i < n; i++) { result[i] = nextInt(); } return result; } public long nextLong() throws java.io.IOException { long val = 0; int c; for (c = fetchByte(); c <= ' '; c = fetchByte()) { } boolean neg = c == '-'; if (c == '-' || c == '+') { c = fetchByte(); } for (; c >= '0' && c <= '9'; c = fetchByte()) { val = (val << 3) + (val << 1) + (c & 15); } return neg ? -val : val; } public long[] nextLong(final int n) throws java.io.IOException { final long[] result = new long[n]; for (int i = 0; i < n; i++) { result[i] = nextLong(); } return result; } public void print(final Object a) throws java.io.IOException { out.write(a.toString().getBytes()); } private static final byte[] SP = new byte[] { 0x20 }; public void printsp(final Object a) throws java.io.IOException { out.write(a.toString().getBytes()); out.write(SP); } private static final byte[] CRLF = System.lineSeparator().getBytes(); public void println() throws java.io.IOException { out.write(CRLF); } public void println(final Object a) throws java.io.IOException { out.write(a.toString().getBytes()); out.write(CRLF); } public void printaln(final int[] a) throws java.io.IOException { for (int i = 0, n = a.length; i < n; i++) { out.write(Integer.toString(a[i]).getBytes()); out.write(CRLF); } } public void printasp(final int[] a) throws java.io.IOException { for (int i = 0, n = a.length; i < n; i++) { out.write(Integer.toString(a[i]).getBytes()); out.write(SP); } } public void printaln(final long[] a) throws java.io.IOException { for (int i = 0, n = a.length; i < n; i++) { out.write(Long.toString(a[i]).getBytes()); out.write(CRLF); } } public void printasp(final long[] a) throws java.io.IOException { for (int i = 0, n = a.length; i < n; i++) { out.write(Long.toString(a[i]).getBytes()); out.write(SP); } } public void printaln(final Object[] a) throws java.io.IOException { for (int i = 0, n = a.length; i < n; i++) { out.write(a[i].toString().getBytes()); out.write(CRLF); } } public void printasp(final Object[] a) throws java.io.IOException { for (int i = 0, n = a.length; i < n; i++) { out.write(a[i].toString().getBytes()); out.write(SP); } } public void flush() throws java.io.IOException { out.flush(); } } }
説明
IO という nested static クラスを作り、これを介して標準入出力、つまり問題のパラメータの読み込みと、結果の出力をやります。main() の中で IO インスタンスを用意して、それを execute() に渡すようにしています。終わったら IO を close() しますが、ここで確実に出力を flush() するようにしています。IO は AutoCloseable にして、try-with-resources 構文が使えるようにしてあります。
入力は、BufferedReader にせず、InputStream のまま取り扱い、自前のバッファを使って buffered read を実現しています (28〜37行目)。
ほとんど整数問題なので、整数の読み取りを高速に行えるよう、nextInt() を用意しています。1文字ずつ読み出し、数字が続く限り10倍して数値化したものを足す、という繰り返しなのですが、ちょっと工夫があり、10倍は8倍(3ビットシフト)と2倍(1ビットシフト)の加算としています。数値化は文字コードに対して 15 (2進数で1111) とのビット論理和を取ることで実行しています。'0' の文字コードは2進数で110000、'1' は 110001、...、'9' は 111001 なので、この方法がうまくいきます (68行目など)。
出力の方は、BufferedOutputStream を使っています。System.out は頻繁に flush() が発生してちょっと効率が悪いので、手前でバッファするよう BufferedOutputStream をかぶせています。non-ASCII 文字の出力は無さそうなので、BufferedWriter にはしていません。