【競プロ精進ログ】ABC146-C

zuka

ABCをコツコツ解いていきます。

本記事は,管理人の競技プロ精進日記としてログを取ったものです。モチベーションを爆上げするために,積極的にアウトプットしていく作戦です。

これから競技プログラミングを始めようと考えている人や,なんとなく敷居が高いと感じている人の参考になれば嬉しく思います。その他の記事は以下をご覧ください。

目次

本記事の概要

Atcoderで初心者用のコンテストとして開催されているAtcoder Beginner Contest(通称ABC)を解いていくものです。今回はABC146-C「Buy an Integer」です。

ポイント

$N \leq 10^8$ですので,全ての$N$について調べてしまっては時間が足りません。そこで,今回は二分探索を利用して「条件を満たす要素」を探していきたいと思います。二分探索の説明は,以下をご覧ください。

また,今回はmain関数の中に関数を書いて見ようと思います。その際利用されるのが「ラムダ式」です。

c++日本語公式ドキュメント:ラムダ式

ラムダ式では,以下のようにしてmain関数の内部で関数を定義することができます。こうすることで,無駄に関数の引数を設定する必要がなくなります。

auto 関数名 = [](引数の型1 引数名1, 引数の型2, 引数名2, ...) { 関数の処理 };

[&] とすることで関数の外部(main関数の内部)で受け取った入力をそのまま利用できるようになります。

おさえるべき内容

 二分探索は「ソートされた配列」から「条件を満たす要素を探し出す」

 ラムダ式を利用すればmain関数の中に関数を定義できるようになる

方針

$N$に関する二分探索を行います。そのとき,二分探索における条件を「高橋君の所持金$X$を整数$N$の値段が超えてしまう」とします。すると,求める答えはleftインデックスであることが分かります。

実装

#include <bits/stdc++.h>
#define _GLIBCXX_DEBUG
#define rep(i, n) for (int i = 0; i < (int)(n); i++)
#define repi(i, a, b) for (int i = (int)(a); i < (int)(b); i++)
using namespace std;

int main(){
  long long A, B, X;
  cin >> A >> B >> X;
  // ラムダ式
  auto calc = [&](long long N){
    return A * N + B * to_string(N).size();
  };

  // Nの最小値は1なので左端は0
  // Nの最大値は10^9なので右端は10^9+1
  long long left = 0;
  long long right = pow(10, 9) + 1;
  // 二分探索
  while(right - left > 1){
    long long mid = (left + right) / 2;
    if (calc(mid) > X) right = mid;
    else left = mid;
  }
  // 左端を出力
  cout << left << endl;
}
よかったらシェアしてね!

コメント

コメントする

目次
閉じる