Problem:
Score : 500 points

Problem Statement

Takahashi and Aoki will play a game. They will repeatedly play it until one of them have N wins in total.

When they play the game once, Takahashi wins with probability A %, Aoki wins with probability B %, and the game ends in a draw (that is, nobody wins) with probability C %.
Find the expected number of games that will be played, and print it as follows.

We can represent the expected value as P/Q with coprime integers P and Q.
Print the integer R between 0 and 10^9+6 (inclusive) such that R \times Q \equiv P\pmod {10^9+7}.
(Such an integer R always uniquely exists under the constraints of this problem.)

Constraints

1 \leq N \leq 100000

0 \leq A,B,C \leq 100

1 \leq A+B

A+B+C=100

All values in input are integers.

Input

Input is given from Standard Input in the following format:

N A B C

Output

Print the expected number of games that will be played, in the manner specified in the statement.

Sample Input 1

1 25 25 50

Sample Output 1

2

Since N=1, they will repeat the game until one of them wins.
The expected number of games played is 2.

Sample Input 2

4 50 50 0

Sample Output 2

312500008

C may be 0.

Sample Input 3

1 100 0 0

Sample Output 3

1

B may also be 0.

Sample Input 4

100000 31 41 28

Sample Output 4

104136146

Solution in Kotlin (1.0.0) (judge verdict: Runtime Error)

fun main(args: Array<String>) {

    /**
     * A : B : C = 勝ち : 負け : 引き分け の確率の時に N 回どちらかが勝つまで勝負を続けるとした時の勝負回数の期待値
     * 組み合わせの計算は事前に配列にO(N) で計算しておいて必要な時に O(1) で取り出せるようにしておく必要がある
     */

    val (n, a, b, c) = readLine()!!.split(" ").map { it.toLong() }
    val modVal = (1e9 + 7).toLong()

    // mod 値テーブルを初期化
    initTable(modVal)

    // 引き分けが存在しない場合での期待値を求める ( 引き分けが入る場合は，求めた期待値を引き分けの割合分，足してあげれば良い

    // 片方が n 回勝つまでに もう片方が i 回かつ場合の期待値
    fun calc_n回勝つまでにもう片方がi回かつ場合の期待値(i: Long): Long {

        val patternNum = combinationModWithTable(n-1 + i, i, modVal)

        // 逆元Mod計算 // おそらく計算の組み合わせ方法が違うので再考が必要

        powMod(inv[100], 4, modVal)

        val probAwinMod = modTimes(listOf(powMod(a, n, modVal), powMod(inv[(a+b).toInt()], n, modVal), powMod(b, i, modVal), powMod(inv[(a+b).toInt()], i, modVal)), modVal)
        val probBwinMod = modTimes(listOf(powMod(b, n, modVal), powMod(inv[(a+b).toInt()], n, modVal), powMod(a, i, modVal), powMod(inv[(a+b).toInt()], i, modVal)), modVal)

        // この部分 OverFlowしてそう
        return modTimes(listOf(patternNum, (probAwinMod + probBwinMod), n + i), modVal)
    }

    var ans = 0L
    for (i in 0 until n) {
        ans = (ans + calc_n回勝つまでにもう片方がi回かつ場合の期待値(i)) % modVal
    }

    // c% 引き分けが入るの -> c / a + b + c  = c/100 で引き分け -> 勝負がつく回数は (100-c) / 100 -> 全体の勝負回数は 100 / (100-c) になる (増える）
    println((ans * 100 / (100 - c) % modVal))
}

/**
 * プロコンで頻出の mod 計算を定義したクラス
 *
 * 参考 : https://qiita.com/drken/items/3b4fdf0a78e7a138cd9a
 */

// 階乗の mod 並びに 逆元の mod を格納するための配列を初期化
private const val MAX = 1e7.toInt()   // MAX は求める必要がある階乗の部分の計算に対してのみ求める
private val fact = LongArray(MAX+1){-1}  // n 番目は　ｎ! の mod
private val finv = LongArray(MAX+1){-1}  // n 番目は n! の逆元
private val inv = LongArray(MAX+1){-1}  // n 番目は n! の逆元


/**
 * 階乗のmod 並びに 逆元 テーブルを初期化
 * それぞれの計算には漸化式を用いており，各逆元の計算は O(1) で行われる．フェルマーの小定理も，拡張Euclid の互除法も必要ない OMG
 * mod値が 1e9+7 だと，途中計算で mod を求める前に Long最大値 を超えるので LongArray を使用
 *
 * テーブル全体(N)ではなく，単体で逆元計算を行うときには上記定理を用いた計算を実行すると O(N) -> O(log modVal) に計算量を削減できる
 *
 * <注意>
 * nCk mod p の計算に用いる際の暗黙の前提 : p > n かつ k! (k<=n) のどれとも p が一致しない  -> 「p が n より大きい素数」 だと条件が満たされやすい
 * 例えば modVal 以上の 階乗のmod値は 0 になるので注意 5C2 mod 3 とかを計算しようとすると分子の階乗部分が 0 になって正しく計算できないので注意
 * 正しくは (5*4 / 2*1) mod 3 = 1 だが，この方式だと (5*4*3*2*1 / 2*1*3*2*1) mod 3 = 0  となってしまう
 */
fun initTable(modVal: Long) {

    //初期値設定
    fact[0] = 1
    fact[1] = 1
    inv[0] = 1 //?
    inv[1] = 1

    for ( i in 2..MAX) {

        // 階乗の mod については普通に掛け算 & mod 計算でOK
        fact[i] = fact[i-1] * i % modVal

        // 各 i に対する逆元を求めて格納しておく (finv 確認 or 直接計算 )

        // 実装上の工夫
        // 1.modVal を足しているのは inv[i] を常に正の値にするため ( inv[i] は常に modVal を前提とした計算で用いるので modVal が加えられていても影響は無い）
        // 2. 新たな inv[i] を求める時に % modVal をしているのは 値のオーバーフローを避けるため & inv[i] は常にm modVal を前提とした計算で 掛け算に用いられるため どの段階で %modVal をとっても影響は無い

        inv[i] = modVal - inv[(modVal % i).toInt()] * (modVal / i) % modVal

        // inv[i] の結果を finv[i-1] に掛け合わせて mod を取った結果が finv[i] ( 逆元の累乗 ) 累乗の逆元 = 逆元の総積
        finv[i] = finv[i-1] * inv[i] % modVal
    }
}


/**
 * 事前に計算した逆元テーブルから nCk mod modVal を計算
 */
fun combinationModWithTable(n: Long, k: Long, modVal: Long): Long {
    val numeTerm = fact[n.toInt()]
    val denomTerm = finv[k.toInt()] * finv[(n-k).toInt()] % modVal

    return (numeTerm * denomTerm % modVal)
}


/**
 * nCk mod modVal を計算する
 *
 * 分子部分は O(N) で計算
 * 分母を考える際に 割り算に対する mod を定義する必要がある
 */
@Deprecated(message = "This Implementation might be wrong. Use combinationModWithTable")
fun combinationMod(n: Long, k: Long, modVal: Long): Long {

    // O(N)
    val nume = factMod(n, modVal)

    // これは実は間違っている
    // 累乗の modVal 後の 逆元 と　累乗の逆元は異なる 式的には
    // r! = q (mod p の場合) でも (r!)^-1 = q^-1 (mod p の場合） は成り立たないということ, いや成り立つかはわからないので使わないほうがbetter
    val denom = (factMod(k, modVal) * factMod(n - k, modVal)) % modVal

    // -> この方針だと OverFlow を避けるために， k! の逆元を求めるために 1 ~ k の各値の逆元を計算しなくてはいけない O(k log K?) は必要なので辛い?

    return modDiv(nume, denom, modVal)
}

private fun factMod(n: Long, modVal: Long): Long {
    var ans = 1L
    for (i in 1..n) {
        ans = (ans * i) % modVal
    }

    return ans
}


fun modTimes(inputs: List<Long>, modVal: Long): Long {
    return inputs.reduce { acc, i -> (acc % modVal) * (i % modVal) % modVal }
}

/**
 * mod の世界での割り算を実装
 *
 * a/b mod p を求めたい場合 mod p における b の逆元(b^-1)を求めて (a * b^-1) mod p とする
 */

fun modDiv(numerator: Long, denominator: Long, modVal: Long): Long {

    // 拡張Euclidの互除法を用いた 逆元計算の実装では 負の 値が返ってくることもあるので (  + modVal) % modVal をする
    val invMod = (invModEuclid(denominator, modVal).first + modVal) % modVal

    return (numerator * invMod) % modVal
}

/**
 * mod modVal の世界での逆元を求める O(log modVal)
 *
 * 定義 a * b mod modVal = 1 となるとき b を mod modVal の世界での逆元と呼ぶ
 *
 * -> x / a mod modVal = x * b mod modVal と書き換える事ができる
 * -> mod の掛け算は逐次計算できるので OverFlow を避けられる （嬉しい）
 *
 * フェルマーの小定理を元にした実装, modVal は素数である必要がある
 */
fun invModFermat(a: Long, modVal: Long): Long {
    return powMod(a, modVal - 2, modVal)
}


/**
 * mod b の世界での a の逆元を求める
 * ユークリッドの互除法に類似した計算を行うので 最悪 O(log modVal) (ユークリッドの互除法の計算量は log modVal 以下になる)
 * -> 平均的には フェルマーの小定理を用いた逆元計算よりも計算量が少なくなる (あちらは 累乗計算で 必ず log(modVal-2) 必要
 *
 * a と modVal は互いに素 である必要がある
 *  <-> a , modVal が互いに素 でないとしたら？
 *
 *  ax + by = c を満たす整数 x, y が存在する必要十分条件は c = k gcd(a,b) を満たす k が存在すること (そうでなければ整数解は存在しない）
 *
 *  ->
 *
 *  ax + by = gcd(a,b) を満たす x, y は存在する
 *
 *  ->
 *
 *  a, b が互いに素 であれば
 *
 *  ax + by = 1 を満たす x, y は存在する といえる
 *
 *  ->
 *
 *  つまり逆元が存在する -> ユークリッドの互除法で解を求める
 *
 *  ※ 「mod p において a の逆元が存在する」 と 「ax + py = 1 となる 整数解 x,y が存在する」 は等価なので
 *     「mod p において a の逆元が存在する」 ための必要十分条件は 「p と a が互いに素」
 *
 *  丁寧に再帰計算で実装する,, アドレスを渡して，グローバル変数のようにみなして計算するのは賢すぎるので変数で渡していくことを考える
 *  -> ２つの値を受け取って２つの値を返す実装に
 *
 *  なお，最終的に用いる値は 返された値の第一要素なので注意 (使いづらい？）また，負の値が返ってくるかもしれないことには注意
 */
fun invModEuclid(a: Long, b: Long) : Pair<Long, Long> {

    // 互除法同様, 渡されたあまりが 0 になったら再帰を終了する
    if (b == 0L) {
        return Pair(1, 0)
    }

    // １つ下の b, a%b に対する計算結果から a, b についての結果を計算する
    val (s, t) = invModEuclid(b, a%b)

    return Pair(t, s - a/b * t)
}

/**
 * a^n mod modVal を計算する
 * 二分累乗法で累乗計算を O(logN) で行いつつ，OverFlow を避けるため適宜 mod 計算を行う
 */
fun powMod(a: Long, n: Long, modVal: Long, ans: Long = 1): Long {

    if (n == 0L) {
        return ans
    }

    // ビット演算の結果 2^0 の桁が 0 の場合は ans に掛けずに次の桁へ
    if (n.and(1L) == 0L) {
        return powMod(a * a % modVal, n.shr(1), modVal, ans)
    }

    // ビット演算の結果 2^9 の毛型 1 の場合は ans を更新
    return powMod(a * a % modVal, n.shr(1), modVal, ans * a % modVal)
}


/**
 * 二分累乗法の実装 a^N を O(logN) で計算
 * 指数部分を２進数で考える -> 指数が2^n になっていなくても問題ない
 */
private fun pow(a: Long, n: Long, ans: Long = 1): Long {

    if (n == 0L) {
        return ans
    }

    // ビット演算の結果 2^0 の桁が 0 の場合は ans に掛けずに次の桁へ
    if (n.and(1L) == 0L) {
        return pow(a * a, n.shr(1), ans)
    }

    // ビット演算の結果 2^9 の毛型 1 の場合は ans を更新
    return pow(a * a, n.shr(1), ans * a)
}