LoginSignup
2
2

More than 5 years have passed since last update.

Codeforces #257 div.1 A

Posted at

概要

一昨日昨日に引き続いて解いていきます。
ようやくC問題ですね。
この問題、分割数も求めれば実際にチョコレートを割るときに使えるかも…?

問題

n*mのチョコレートをk回割りたい。
割るときは、よくある溝に沿って割らないといけない。
一番小さいチョコが最大の大きさになるように割った時、その大きさを求めよ。

1 \leq n,m \leq 10^9 \\
1 \leq k \leq 2 \cdot 10^9

アルゴリズム

n,m,kがいつも通りでかいので、O(n)では間に合いませんね。
面積が$10^18$あるチョコレート、見てみたい。単位がわからんけど。
ということは、全部の割るパターンを網羅はできないです。
Div.2 A問題なら全探索もありですが、これは生憎Div.1 A問題ですね。

こういう時は、実際に割って考えてみましょう。

さて、適当に割ってみると、どうも縦と横、両方向から割るのはダメそうです。
縦なら縦、横なら横だけで割ると大きくできそうです。
割る回数が多い時は、しょうがなく両方向から割る感じですね。

長い辺を割るか、短い辺を割るかは場合によって違いそうです。
例えば、4×3を割るとき、k=1なら4の辺を割ると6になって最大ですが、k=2なら3の辺を割った場合が4で最大です。
ここに法則を求めるのは難しそうなので、両方求めて大きい方を採用します。
オーダー的には変化しないので問題ないでしょう。

なお、$(n-1)+(m-1) < k$なら割る回数が多すぎて、割ることができません。
こういう場合は-1を返して終わります。

まとめると、

  1. 割る回数が多過ぎたら-1

  2. 両方の辺を割らないといけない時は、単方向から割り切って、残りの回数でもう一方向から割る

  3. それ以外の時は、縦横それぞれの方向で割った結果を比較

というシンプルな処理で実現できそうです。
これをコードに落とします。

解答

Scalaっぽさはありません。
関数型感出せるんかな、こういう処理…。

import scala.math.BigInt

object Main extends App {
  val sc = new java.util.Scanner(System.in)
  val n,m,k = sc.nextInt

  def solve( n: BigInt, m: BigInt, k: BigInt ): BigInt = {

    if( k == 0 )
      n * m
    else if( (n-1) + (m-1) < k )
      -1
    else {
      val shortSide = n.min(m)
      val longSide = n.max(m)

      // 両方の辺を割らないといけない場合
      if( longSide < (k+1) ) {
        solve(1, m, (k + 1) - n).max(
          solve(n, 1, (k + 1) - m)
        )
      }
      // 片方向からだけ割って、大きい方を採用
      else {
        val nCut = ( n / (k+1) ) * m
        val mCut = ( m / (k+1) ) * n
        nCut.max(mCut)
      }
    }
  }

  println( solve( n, m, k ) )
}

結果

Time: 218 ms
Memoy: 0 KB

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2