Problem p03025 (python)

Fixed submission:
import os
import sys

sys.setrecursionlimit(2147483647)
INF = float('inf')

if os.getenv('LOCAL'):
    sys.stdin = open('_in.txt')


def mod_inv(a):
    """
    a の逆元
    :param int a:
    :return:
    """
    return pow(a, MOD - 2, MOD)


# https://atcoder.jp/contests/abc066/submissions/5721975
def mod_invs(max, mod):
    """
    逆元のリスト 0 から max まで
    :param max:
    :param mod:
    :return:
    """
    invs = [1] * (max + 1)
    for x in range(2, max + 1):
        invs[x] = (-(mod // x) * invs[mod % x]) % mod
    return invs


def factorials(max, mod=None):
    """
    階乗 0!, 1!, 2!, ..., max!
    :param int max:
    :param int mod:
    :return:
    """
    ret = [1]
    n = 1
    if mod:
        for i in range(1, max + 1):
            n *= i
            n %= mod
            ret.append(n)
    else:
        for i in range(1, max + 1):
            n *= i
            ret.append(n)
    return ret


MOD = 10 ** 9 + 7
N, A, B, C = list(map(int, sys.stdin.readline().split()))
# R * Q % MOD == P ってことは
# P * inv(Q) % MOD == R なのでこれを求めればいい

# --- ふつうに期待値求めてみる ---
# # 引き分けなしの値にする
# A /= 100 - C
# B /= 100 - C
# C /= 100
#
# # 引き分けなしで A が勝つときの回数の期待値
# a = 0
# for i in range(N):
#     a += A ** N * B ** i * math.factorial(N + i - 1) / math.factorial(N - 1) / math.factorial(i) * (N + i)
# # 引き分けなしで B が勝つときの回数の期待値
# b = 0
# for i in range(N):
#     b += B ** N * A ** i * math.factorial(N + i - 1) / math.factorial(N - 1) / math.factorial(i) * (N + i)
#
# # C 以外が起こる期待値なので 1/(1-C) をかける
# ans = (a + b) / (1 - C)
# print(ans)


# --- 愚直解 ---
# ans = 0
# # 引き分けなしで A が勝つときの回数の期待値
# for i in range(N):
#     ans += pow(A * mod_inv(100 - C), N, MOD) \
#            * pow(B * mod_inv(100 - C), i, MOD) \
#            * math.factorial(N + i - 1) \
#            * mod_inv(math.factorial(N - 1) * math.factorial(i)) \
#            * (N + i)
#     ans %= MOD
# # 引き分けなしで B が勝つときの回数の期待値
# for i in range(N):
#     ans += pow(B * mod_inv(100 - C), N, MOD) \
#            * pow(A * mod_inv(100 - C), i, MOD) \
#            * math.factorial(N + i - 1) \
#            * mod_inv(math.factorial(N - 1) * math.factorial(i)) \
#            * (N + i)
#     ans %= MOD
# # 引き分けを考慮
# ans *= 100 * mod_inv(100 - C)
# print(ans % MOD)


# invs = mod_invs(max=max(N, 100), mod=MOD)
# fs = factorials(max=2 * N, mod=MOD)
# ans = 0
# # 引き分けなしで A が勝つときの回数の期待値
# for i in range(N):
#     ans += pow(A * invs[100 - C], N, MOD) \
#            * pow(B * invs[100 - C], i, MOD) \
#            * fs[N + i - 1] \
#            * mod_inv(fs[N - 1] * fs[i]) \
#            * (N + i)
#     ans %= MOD
# # 引き分けなしで B が勝つときの回数の期待値
# for i in range(N):
#     ans += pow(B * invs[100 - C], N, MOD) \
#            * pow(A * invs[100 - C], i, MOD) \
#            * fs[N + i - 1] \
#            * mod_inv(fs[N - 1] * fs[i]) \
#            * (N + i) % MOD
#     ans %= MOD
# # 引き分けを考慮
# ans *= 100 * invs[100 - C]
# print(ans % MOD)


invs = mod_invs(max=max(N, 100), mod=MOD)
fs = factorials(max=2 * N, mod=MOD)
ans = 0
for i in range(N):
    ans += ((pow(A * invs[100 - C], N, MOD) * pow(B * invs[100 - C], i, MOD)
             + pow(B * invs[100 - C], N, MOD) * pow(A * invs[100 - C], i, MOD))
            * fs[N + i - 1] * mod_inv(fs[N - 1] * fs[i])
            * (N + i))
    ans %= MOD
# 引き分けを考慮
ans *= 100 * invs[100 - C]
print(ans % MOD)

Buggy submission (verdict: Runtime Error):
import itertools
import os
import sys

sys.setrecursionlimit(2147483647)
INF = float('inf')

if os.getenv('LOCAL'):
    sys.stdin = open('_in.txt')


def mod_inv(a):
    """
    a の逆元
    :param int a:
    :return:
    """
    return pow(a, MOD - 2, MOD)


# https://atcoder.jp/contests/abc066/submissions/5721975
def mod_invs(max, mod):
    """
    逆元のリスト 0 から max まで
    :param max:
    :param mod:
    :return:
    """
    invs = [1] * (max + 1)
    for x in range(2, max + 1):
        invs[x] = (-(mod // x) * invs[mod % x]) % mod
    return invs


def factorials(max, mod=None):
    """
    階乗 0!, 1!, 2!, ..., max!
    :param int max:
    :param int mod:
    :return:
    """
    ret = [1]
    n = 1
    if mod:
        for i in range(1, max + 1):
            n *= i
            n %= mod
            ret.append(n)
    else:
        for i in range(1, max + 1):
            n *= i
            ret.append(n)
    return ret


MOD = 10 ** 9 + 7
N, A, B, C = list(map(int, sys.stdin.readline().split()))

# R * Q % MOD == P ってことは
# P * inv(Q) % MOD == R なのでこれを求めればいい

# --- ふつうに期待値求めてみる ---
# # 引き分けなしの値にする
# A /= 100 - C
# B /= 100 - C
# C /= 100
#
# # 引き分けなしで A が勝つときの回数の期待値
# a = 0
# for i in range(N):
#     a += A ** N * B ** i * math.factorial(N + i - 1) / math.factorial(N - 1) / math.factorial(i) * (N + i)
# # 引き分けなしで B が勝つときの回数の期待値
# b = 0
# for i in range(N):
#     b += B ** N * A ** i * math.factorial(N + i - 1) / math.factorial(N - 1) / math.factorial(i) * (N + i)
#
# # C 以外が起こる期待値なので 1/(1-C) をかける
# ans = (a + b) / (1 - C)
# print(ans)


# --- 愚直解 ---
# ans = 0
# # 引き分けなしで A が勝つときの回数の期待値
# for i in range(N):
#     ans += pow(A * mod_inv(100 - C), N, MOD) \
#            * pow(B * mod_inv(100 - C), i, MOD) \
#            * math.factorial(N + i - 1) \
#            * mod_inv(math.factorial(N - 1) * math.factorial(i)) \
#            * (N + i)
#     ans %= MOD
# # 引き分けなしで B が勝つときの回数の期待値
# for i in range(N):
#     ans += pow(B * mod_inv(100 - C), N, MOD) \
#            * pow(A * mod_inv(100 - C), i, MOD) \
#            * math.factorial(N + i - 1) \
#            * mod_inv(math.factorial(N - 1) * math.factorial(i)) \
#            * (N + i)
#     ans %= MOD
# # 引き分けを考慮
# ans *= 100 * mod_inv(100 - C)
# print(ans % MOD)


# invs = mod_invs(max=max(N, 100), mod=MOD)
# fs = factorials(max=2 * N, mod=MOD)
# ans = 0
# # 引き分けなしで A が勝つときの回数の期待値
# for i in range(N):
#     ans += pow(A * invs[100 - C], N, MOD) \
#            * pow(B * invs[100 - C], i, MOD) \
#            * fs[N + i - 1] \
#            * mod_inv(fs[N - 1] * fs[i]) \
#            * (N + i)
#     ans %= MOD
# # 引き分けなしで B が勝つときの回数の期待値
# for i in range(N):
#     ans += pow(B * invs[100 - C], N, MOD) \
#            * pow(A * invs[100 - C], i, MOD) \
#            * fs[N + i - 1] \
#            * mod_inv(fs[N - 1] * fs[i]) \
#            * (N + i) % MOD
#     ans %= MOD
# # 引き分けを考慮
# ans *= 100 * invs[100 - C]
# print(ans % MOD)


invs = mod_invs(max=max(N, 100), mod=MOD)
fs = factorials(max=2 * N, mod=MOD)
A *= invs[100 - C]
B *= invs[100 - C]
A_powers = list(itertools.accumulate([1] * (N + 1), lambda p, _: p * A % MOD))
B_powers = list(itertools.accumulate([1] * (N + 1), lambda p, _: p * B % MOD))
ans = 0
for i in range(N):
    ans += ((A_powers[N] * B_powers[i] + B_powers[N] * A_powers[i])
            * fs[N + i - 1] * mod_inv(fs[N - 1] * fs[i])
            * (N + i))
    ans %= MOD
# 引き分けを考慮
ans *= 100 * invs[100 - C]
print(ans % MOD)

Buggy submission (verdict: Runtime Error):
import os
import sys
import numpy as np

sys.setrecursionlimit(2147483647)
INF = float('inf')

if os.getenv('LOCAL'):
    sys.stdin = open('_in.txt')


def mod_inv(a):
    """
    a の逆元
    :param int a:
    :return:
    """
    return pow(a, MOD - 2, MOD)


# https://atcoder.jp/contests/abc066/submissions/5721975
def mod_invs(max, mod):
    """
    逆元のリスト 0 から max まで
    :param max:
    :param mod:
    :return:
    """
    invs = [1] * (max + 1)
    for x in range(2, max + 1):
        invs[x] = (-(mod // x) * invs[mod % x]) % mod
    return invs


def factorials(max, mod=None):
    """
    階乗 0!, 1!, 2!, ..., max!
    :param int max:
    :param int mod:
    :return:
    """
    ret = [1]
    n = 1
    if mod:
        for i in range(1, max + 1):
            n *= i
            n %= mod
            ret.append(n)
    else:
        for i in range(1, max + 1):
            n *= i
            ret.append(n)
    return ret


MOD = 10 ** 9 + 7
N, A, B, C = list(map(int, sys.stdin.readline().split()))
# R * Q % MOD == P ってことは
# P * inv(Q) % MOD == R なのでこれを求めればいい

# --- ふつうに期待値求めてみる ---
# # 引き分けなしの値にする
# A /= 100 - C
# B /= 100 - C
# C /= 100
#
# # 引き分けなしで A が勝つときの回数の期待値
# a = 0
# for i in range(N):
#     a += A ** N * B ** i * math.factorial(N + i - 1) / math.factorial(N - 1) / math.factorial(i) * (N + i)
# # 引き分けなしで B が勝つときの回数の期待値
# b = 0
# for i in range(N):
#     b += B ** N * A ** i * math.factorial(N + i - 1) / math.factorial(N - 1) / math.factorial(i) * (N + i)
#
# # C 以外が起こる期待値なので 1/(1-C) をかける
# ans = (a + b) / (1 - C)
# print(ans)


# --- 愚直解 ---
# ans = 0
# # 引き分けなしで A が勝つときの回数の期待値
# for i in range(N):
#     ans += pow(A * mod_inv(100 - C), N, MOD) \
#            * pow(B * mod_inv(100 - C), i, MOD) \
#            * math.factorial(N + i - 1) \
#            * mod_inv(math.factorial(N - 1) * math.factorial(i)) \
#            * (N + i)
#     ans %= MOD
# # 引き分けなしで B が勝つときの回数の期待値
# for i in range(N):
#     ans += pow(B * mod_inv(100 - C), N, MOD) \
#            * pow(A * mod_inv(100 - C), i, MOD) \
#            * math.factorial(N + i - 1) \
#            * mod_inv(math.factorial(N - 1) * math.factorial(i)) \
#            * (N + i)
#     ans %= MOD
# # 引き分けを考慮
# ans *= 100 * mod_inv(100 - C)
# print(ans % MOD)


# invs = mod_invs(max=max(N, 100), mod=MOD)
# fs = factorials(max=2 * N, mod=MOD)
# ans = 0
# # 引き分けなしで A が勝つときの回数の期待値
# for i in range(N):
#     ans += pow(A * invs[100 - C], N, MOD) \
#            * pow(B * invs[100 - C], i, MOD) \
#            * fs[N + i - 1] \
#            * mod_inv(fs[N - 1] * fs[i]) \
#            * (N + i)
#     ans %= MOD
# # 引き分けなしで B が勝つときの回数の期待値
# for i in range(N):
#     ans += pow(B * invs[100 - C], N, MOD) \
#            * pow(A * invs[100 - C], i, MOD) \
#            * fs[N + i - 1] \
#            * mod_inv(fs[N - 1] * fs[i]) \
#            * (N + i) % MOD
#     ans %= MOD
# # 引き分けを考慮
# ans *= 100 * invs[100 - C]
# print(ans % MOD)


invs = mod_invs(max=max(N, 100), mod=MOD)
fs = factorials(max=2 * N, mod=MOD)
ans = 0
for i in range(N):
    ans += ((pow(A * invs[100 - C], N, MOD) * pow(B * invs[100 - C], i, MOD)
             + pow(B * invs[100 - C], N, MOD) * pow(A * invs[100 - C], i, MOD))
            * fs[N + i - 1] * mod_inv(fs[N - 1] * fs[i])
            * (N + i))
    ans %= MOD
# 引き分けを考慮
ans *= 100 * invs[100 - C]
print(ans % MOD)