競技プログラミングのためのF#入門
GitHub上の対応ディレクトリ 公式ページ 要点: 組み合わせの処理 解説
数学的な組み合わせ処理とmod
つきnCr
の実装だけです. 後者は自分用のライブラリ・関数を用意しておくべきです.
入出力
| let N,K = stdin.ReadLine().Split() |> Array.map int64 |> (fun x -> x.[0],x.[1])
solve N K |> Array.iter stdout.WriteLine
|
順列・組み合わせ系の関数
mod
つきの計算の場合, いくつかの処理が簡略化できます. 逆数を取る走査もかけ算で表せるためそれを前提にした実装です. 単純に順列はp
, 組み合わせはc
にしています.
| let MOD = 1_000_000_007L
let p n r = let rec frec acc n r = if r=0L then acc else frec ((n*acc)%MOD) (n-1L) (r-1L) in frec 1L n r
let rec powm x n = if n=0L then 1L else if n%2L=0L then powm (x*x % MOD) (n/2L) else (x * (powm x (n-1L)) % MOD)
let inv a = powm a (MOD-2L)
let c n r = ((p n r) * (inv (p r r))) % MOD
|
これ以外の順列・組み合わせ系の関数実装サンプルがArithmetics.fsxにあります. 必要に応じて参照してください.
各i
に対する計算
| [|1L..K|] |> Array.map (fun i -> c (N-K+1L) i * c (K-1L) (i-1L) % MOD)
|
まとめ
| let solve N K =
let MOD = 1_000_000_007L
let p n r = let rec frec acc n r = if r=0L then acc else frec ((n*acc)%MOD) (n-1L) (r-1L) in frec 1L n r
let rec powm x n = if n=0L then 1L else if n%2L=0L then powm (x*x % MOD) (n/2L) else (x * (powm x (n-1L)) % MOD)
let inv a = powm a (MOD-2L)
let c n r = ((p n r) * (inv (p r r))) % MOD
[|1L..K|] |> Array.map (fun i -> c (N-K+1L) i * c (K-1L) (i-1L) % MOD)
let N,K = stdin.ReadLine().Split() |> Array.map int64 |> (fun x -> x.[0],x.[1])
solve N K |> Array.iter stdout.WriteLine
|
Previous: 093 D - Transit Tree Path Next: 095 D - Xor Sum 4 back to top