競技プログラミングのためのF#入門
GitHub上の対応ディレクトリ 公式ページ 要点: アルゴリズム, ループを減らす 入出力
| let N,K = stdin.ReadLine().Split() |> Array.map int |> (fun x -> x.[0],x.[1])
solve N K |> stdout.WriteLine
|
方針
これもよく出てくる処理です. 単純に三重ループを回すとTLEで時間内に終わりません. 時間内に終わらせる工夫が必要です.
解説
単純な処理の累積
三つ目のループをどうにかして回避する必要があります. 発想を転換して二つ目までのループで次のような和を作りましょう.
| [| for i in 1..N do for j in 1..N do yield K-i-j |]
|
この配列はN^2
個の要素を持っています. 仮に三つ目のループを回すとしてその変数をx
とすると, x = K-i-j
が所定の範囲である1
からN
におさまっていれば条件をみたします. そこでfilter
を使ってチェックしましょう.
| [| for i in 1..N do for j in 1..N do yield K-i-j |]
|> Array.filter (fun x -> 1<=x && x<=N)
|
これで条件をみたす要素だけが抜き出せました. あとはこの配列の長さを取れば終わりです.
| [| for i in 1..N do for j in 1..N do yield K-i-j |]
|> Array.filter (fun x -> 1<=x && x<=N)
|> Array.length
|
for
の中でフィルターする
他の言語と同じくfor
の内包表記の中で次のようにフィルターできます.
| [| for i in 1..N do for j in 1..N do let x=K-i-j in if 1<=x && x<=N then x |]
|
あとは同じく配列の長さを取れば終わりです.
| let solve N K =
[| for i in 1..N do for j in 1..N do let x=K-i-j in if 1<=x && x<=N then x |] |> Array.length
|
filter
でN^2
個の配列を再びチェックしなくていい分, こちらの方が二割ほど速いです.
Previous: A04 - Binary Representation 1 Next: A06 - How Many Guests? back to top