📖

ABC227 C - ABC conjecture C++解答例

2021/11/14に公開

ABC227 C - ABC conjectureをC++で解きます。

問題

問題文をAtCoderのページより引用します。

問題文

正の整数Nが与えられます。
A \leq B \leq CかつABC \leq Nであるような正の整数の組(A, B, C)の個数を求めてください。
なお、制約の条件下で答えは2^{63}未満であることが保証されます。

制約

  • 1 \leq N \leq 10^{11}
  • Nは整数である

解答例

工夫した全探索で解く

正の整数の組(A, B, C)を全探索して個数を数え上げることを考えます。
問題文の条件より、3つの数のうち一番小さいAを決め打ちすると、他の2つの数の大きさはA以上になることがわかります。
したがって、Aを決め打ちしたとき、3つの数の積ABCの大きさは必ずA^3以上になります。

このことから、3つの数の積ABCN以下になるような組み合わせを全探索したいわけですが、Aを決め打ちしたとき、すでにN < A^3となってしまうようなAは探索しなくてもよいことになります。
これでAの探索範囲を1 \leq A \leq \sqrt[3]{N}と決めることができました。

次にBの探索範囲を決めます。Aの値が決定されているとき、Bの値はA以上を取ります。また、Bの値が決まったときCが取れる値はB以上です。
したがって、Bが取れる値の範囲はA^3 \leq A \times B^2 \leq N、すなわちA \leq B \leq \sqrt{\frac{N}{A}}となります。

次にCの探索範囲を決めるのですが、A, Bの2つの値が決まったとき、問題文の条件よりCの取れる最大値は\lfloor \frac{N}{A \times B} \rfloorと計算することができます。最大値がわかったので、Cは1から\lfloor \frac{N}{A \times B} \rfloorまでの値を取ることができるとわかります。
ただし、Cの値はB以上でなければなりません。そのため、Cの取れる値は1以上\lfloor \frac{N}{A \times B} \rfloor以下の値のうち、B未満の値を取り除いた値になります。数式で表すと\lfloor \frac{N}{A \times B} \rfloor - B + 1です。

実装例

実際の実装例を以下に示します。Cの場合の数を計算する際の床関数ですが、C++では整数の割り算を行ったときに小数点以下が切り捨てられる(床関数と同じ動作をする)ので特に何も考えずに実装できます。

c.cpp
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
 
int main() {
  int64_t N;
  std::cin >> N;
 
  int64_t count = 0;
  // Aの値を全探索する
  for (int64_t i = 1; i * i * i <= N; i++) {
    // Bの値を全探索する
    for (int64_t j = i; i * j * j <= N; j++) {
      // AとBを決めればCが取れる値の場合の数が決まる
      count += N / (i * j) - j + 1;
    }
  }
 
  std::cout << count << std::endl;
 
  return 0;
}

実際に提出したコードはこちら

Discussion