結果
問題 | No.117 組み合わせの数 |
ユーザー | Daisuke Miyakawa |
提出日時 | 2022-06-18 09:51:26 |
言語 | PyPy3 (7.3.15) |
結果 |
RE
|
実行時間 | - |
コード長 | 2,391 bytes |
コンパイル時間 | 201 ms |
コンパイル使用メモリ | 82,464 KB |
実行使用メモリ | 265,864 KB |
最終ジャッジ日時 | 2024-10-09 20:51:36 |
合計ジャッジ時間 | 1,278 ms |
ジャッジサーバーID (参考情報) |
judge2 / judge4 |
(要ログイン)
ソースコード
class ModComb: """\ x^N mod p 、またそれを前提とした nCr の計算を前処理付きで高速に計算する """ def __init__(self, N, p: int = 1_000_000_007): """\ :param N: 乗数の最大値 :param p: 剰余に用いる数。このクラスが正しく機能するためには素数である必要がある """ self._N = N self._p = p self._factorial_cache = {0: 1} for i in range(1, N + 1): self._factorial_cache[i] = (self._factorial_cache[i - 1] * i) % p def factorial(self, n): return self._factorial_cache[n] def inverse(self, x): """xの逆数 (mod p) を返す""" # フェルマーの小定理からxの逆数をx'とすると x' = x^(p-2) mod p k = self._p - 2 ret = 1 y = x while k: if k & 1: ret = (ret * y) % self._p y = (y * y) % self._p k //= 2 return ret def P(self, n, r) -> int: """nPr mod p を求める""" if n == 0 or n < r: return 0 a = self.factorial(n) b = self.factorial(n - r) return (a * b) % self._p def C(self, n, r) -> int: """nCr mod p を求める""" if n == 0 or n < r: return 0 if r == 0: return 1 a = self.factorial(n) b = self.factorial(n - r) c = self.factorial(r) bc = (b * c) % self._p return a * self.inverse(bc) % self._p def H(self, n, r) -> int: """nHr mod p (重複組合せ) を求める""" return self.C(n + r - 1, r) def main(): import re import sys if len(sys.argv) > 1: args = sys.argv[1:] else: T = int(input()) args = [input() for _ in range(T)] mc = ModComb(10 ** 6) for arg in args: m = re.match(r"([CPH])\((\d+)\s*,\s*(\d+)\)", arg) if m: n, r = int(m.group(2)), int(m.group(3)) if m.group(1) == "P": print(mc.P(n, r)) continue elif m.group(1) == "C": print(mc.C(n, r)) continue elif m.group(1) == "H": print(mc.H(n, r)) continue raise RuntimeError(f"Unknown format \"{arg}\"") if __name__ == "__main__": main()