TopCoder SRM 564 Div1 Medium: AlternateColors2

コード

public class AlternateColors2 {

    public long countWays(int n, int k) {
	long ans = 0;
	for (int red = 1; red <= k; red++) {
	    int notred = k - red;// k番目の赤ボールが破壊される前に破壊される赤以外のボールの数
	    int step = red - 1;

	    if (step * 2 < notred) {
		// notredがstep*2以内に収まらない場合、
		// k番目に破壊されるはずのボールが破壊されなくなってしまう
		continue;
	    }

	    if (step * 2 == notred) {
		// 全てのステップでRGBが破壊されている場合
		long rest = n - k;
		// k番目に赤が破壊された後のn-k個のボールの色は何でも良い。
		// よってこの時、重複組み合わせで(rest+2)!/(rest!2!)
		ans += (rest + 2) * (rest + 1) / 2;
	    } else if (notred < step) {
		// k番目に赤が破壊される前に全てのBGが破壊されてしまう時
		// 考えうる青の個数は0〜notredの notred+1 通りで、赤の個数、緑の個数はそれによって1通りに確定する
		ans += notred + 1;
	    } else {
		// k番目に赤が破壊される前に全てのBGが破壊される場合、
		// 考えうる青の個数は(notred-step)〜stepの step-(notred-step)+1 通りである
		// 赤の個数、緑の個数はそれによって1通りに確定する
		ans += step - (notred - step) + 1;

		// k番目の赤が破壊された後、青が残っているとすると、青の個数はred個以上である。この個数はn-k通りである。
		// この時、緑は残っていないので、緑の個数はnotred-step個の1通りである。
		ans += n - k;

		// k番目の赤が破壊された後、緑が残っているとした場合も同様
		ans += n - k;
	    }
	}
	return ans;
    }
}