結果

問題 No.3397 Max Weighted Floor of Linear
コンテスト
ユーザー 👑 Mizar
提出日時 2025-11-10 22:56:50
言語 Haskell
(9.10.1)
結果
AC  
実行時間 330 ms / 2,000 ms
コード長 3,280 bytes
記録
コンパイル時間 10,142 ms
コンパイル使用メモリ 206,096 KB
実行使用メモリ 12,160 KB
最終ジャッジ日時 2025-12-03 23:30:50
合計ジャッジ時間 17,714 ms
ジャッジサーバーID
(参考情報)
judge4 / judge5
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample AC * 3
other AC * 23
権限があれば一括ダウンロードができます
コンパイルメッセージ
Loaded package environment from /home/judge/.ghc/x86_64-linux-9.10.1/environments/default
[1 of 2] Compiling Main             ( Main.hs, Main.o )
[2 of 2] Linking a.out

ソースコード

diff #
raw source code

{-# LANGUAGE BangPatterns #-}
{-# OPTIONS_GHC -O2 #-}

module Main where

import Data.Maybe (fromJust)
import qualified Data.ByteString.Char8 as BS
import Control.Monad  (replicateM, replicateM_)
import Data.Int (Int64)

tuplify2 (x:y:_) = (x,y)
tuplify2 _ = undefined

--Input functions with ByteString
readInt = fst . fromJust . BS.readInt64
readIntTuple = tuplify2 . map readInt . BS.words
readIntList = map readInt . BS.words
readInt64 = fst . fromJust . BS.readInt64
readInt64Tuple = tuplify2 . map readInt64 . BS.words
readInt64List = map readInt64 . BS.words

getInt = readInt <$> BS.getLine
getIntList = readIntList <$> BS.getLine
getIntNList n = map readIntList <$> replicateM (fromIntegral n) BS.getLine
getIntMatrix = map readIntList . BS.lines <$> BS.getContents
getIntTuple = readIntTuple <$> BS.getLine
getIntNTuples n = map readIntTuple <$> replicateM (fromIntegral n) BS.getLine
getIntTuples = map readIntTuple . BS.lines <$> BS.getContents
getInt64 = readInt64 <$> BS.getLine
getInt64List = readInt64List <$> BS.getLine
getInt64NList n = map readInt64List <$> replicateM (fromIntegral n) BS.getLine
getInt64Matrix = map readInt64List . BS.lines <$> BS.getContents
getInt64Tuple = readInt64Tuple <$> BS.getLine
getInt64NTuples n = map readInt64Tuple <$> replicateM (fromIntegral n) BS.getLine
getInt64Tuples = map readInt64Tuple . BS.lines <$> BS.getContents


{-|
Max Weighted Floor (mwf)
  mwf(n,m,a,b,c,d) = max_{0 <= x < n} a*x + b*floor((c*x + d)/m)
を返す非再帰(反復)実装。

前提:
  - n > 0, m > 0

計算量/メモリ:
  - 時間: O(log m)(ユークリッド互除法的再帰による構造縮約)
  - 追加メモリ: O(1)
-}
mwf :: Int64 -> Int64 -> Int64 -> Int64 -> Int64 -> Int64 -> Int64
mwf n0 m0 a0 b0 c0 d0 =
  let !sum0 = 0
      !max0 = b0 * (d0 `div` m0)     -- x = 0 のとき
  in go n0 m0 a0 b0 c0 d0 sum0 max0
  where
    go :: Int64 -> Int64 -> Int64 -> Int64 -> Int64 -> Int64
       -> Int64 -> Int64 -> Int64
    go !n !m !a !b !c !d !sumAcc !maxAcc =
      let (q1, c') = c `divMod` m
          !a'      = a + b * q1
          (q2, d') = d `divMod` m
          !sum'    = sumAcc + b * q2
          !max'    = max maxAcc sum'
          !ymax    = (c' * (n - 1) + d') `div` m
      in if ymax == 0
           then max max' (sum' + a' * (n - 1))
           else
             if a' >= 0
               then
                 let !max'' = max max' (sum' + a' * (n - 1) + b * ymax)
                 in  go ymax c' b a' m (m - d' - 1) sum' max''
               else
                 let !sum'' = sum' + a' + b
                 in  go ymax c' b a' m (m - d' - 1) sum'' max'

{-|
max_{l <= x < r} a*x + b*floor((c*x + d)/m) を返す。

既存の mwf(n,m,...)(0 <= x < n)を用いる。
前提: l < r, m > 0
-}
mwfLr :: Int64 -> Int64 -> Int64 -> Int64 -> Int64 -> Int64 -> Int64 -> Int64
mwfLr l r m a b c d
  | l >= r || m <= 0 = error "mwfLR: require l < r and m > 0"
  | otherwise =
      let n        = r - l
          (q, d')  = (c * l + d) `divMod` m
      in a * l + b * q + mwf n m a b c d'

{-|
入出力(複数ケース)
-}
solve :: IO ()
solve = do
  t <- getInt64
  replicateM_ (fromIntegral t :: Int) $ do
    [n, m, a, b, c, d] <- getInt64List
    print (mwf n m a b c d)

main :: IO ()
main = solve
0