質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Haskell

Haskellは高い機能性をもった関数型プログラミング言語で、他の手続き型プログラミング言語では難しいとされている関数でも容易に行うことができます。強い静的型付け、遅延評価などに対応しています。

Q&A

解決済

2回答

1127閲覧

HaskellでAtCoder ABC145-Dにおいて、自分で以下の書いたコードのどこで0除算がされているかわからない。

RheoTommy

総合スコア13

Haskell

Haskellは高い機能性をもった関数型プログラミング言語で、他の手続き型プログラミング言語では難しいとされている関数でも容易に行うことができます。強い静的型付け、遅延評価などに対応しています。

0グッド

0クリップ

投稿2019/12/12 10:08

タイトル通りですが、下記のコードにおいてどこで0除算がされているかわかりません。

該当のAtCoderリンク

当方Haskellを始めたばかりで、このプログラムが問題をとけるプログラムなのかどうかという確証も持てませんが、下記の二点について助言をいただきたいです。

  1. 0除算が発生している箇所
  2. このプログラムがこの問題を解決できるものか
  3. 1において、解決できない場合、正しいアルゴリズムはなにか。また、どうやって実装するか。(流れだけ)

試したこと

  • m<=0のときの返り値を1で一定にする
  • n==mのときの返り値を1で一定にする

該当コード

Haskell

1import Control.Monad 2import Data.Array 3import qualified Data.ByteString.Char8 as BS 4import Data.List 5import Data.Maybe 6 7readInts :: IO [Int] 8readInts = map (fst . fromJust . BS.readInt) . BS.words <$> BS.getLine 9 10main = do 11 [x, y] <- map read . words <$> getLine 12 print $ solve x y `mod` 1000000007 13 14solve :: Int -> Int -> Int 15solve x y = sum [check x y a | a <- [0 .. x]] 16 17check :: Int -> Int -> Int -> Int 18check x y a 19 | x - a `mod` 2 == 1 = 0 20 | y == (2 * a) + b = c (a + b) a 21 | otherwise = 0 22 where 23 b = (x - a) `div` 2 24 c n m = product [n,n - 1 .. 1] `div` (product [m,m - 1 .. 1] * product [n - m,n - m - 1 .. 1]) 25

エラーが起きるテスト(入力)

terminal

1999999 999999

正しい出力

terminal

1151840682

手元環境でのエラー(Intellij-Haskell)

termial

1/usr/bin/stack build --exec AtCoder-exe 2999999 999999 3AtCoder-exe: divide by zero 4Received ExitFailure 1 when running 5Raw command://ここには実行ファイルの絶対パスがあります。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

1から66までの素因数には2が64個以上含まれているので、product [1..n]はnが66以上だと結果が0になってしまいます(その前にオーバーフローしますが…)。cの定義を工夫し、オーバーフローしないような実装にしましょう(参考: https://stackoverflow.com/questions/1838368/calculating-the-amount-of-combinations )

投稿2019/12/12 12:33

fumieval

総合スコア47

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

RheoTommy

2019/12/12 21:18

なるほど…。ちなみに、この方法以外に、組み合わせのnCrを求める方法ありますかね? 便利な関数とかがあればいいのですが…。 このコードは nCr=n!/r!(n-r)! をもとに作ったのですが、確かに計算結果は大きくなりますね…。
RheoTommy

2019/12/12 21:42

確か重複のない組み合わせをリストで返す関数があった気がします。 それを使い、lenghtで長さを求めればいいですかね? ただ、実行時間が測りしれなさそうです。
guest

0

https://blog.miz-ar.info/2018/01/debugging-haskell-program/ を参考にスタックトレースを出したりtraceShowIdしたりしてわかったことを報告しますと、
c関数における div の分母

(product [m,m - 1 .. 1] * product [n - m,n - m - 1 .. 1])

が0を返したことによるエラーのようです。
詳細は私もわからないのですが、 m がある程度大きな数の場合 product [m,m - 1 .. 1]0 を返してしまうようです。

例:

> product [100, 99 .. 1] :: Int 0

桁あふれが起きているのだと思いますが、なぜ 0 になるかはわからず済みません。

これが正しい回答になるかはわかりませんが、とりあえず対症療法をするなら Int の代わりに Integer を使えば良いでしょう。
ただし、当然実行時間はその分長くなるので、TLEになる可能性が高いですが...。

投稿2019/12/12 11:59

igrep

総合スコア428

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問