Problem p02588 (C++) — buggy submission, verdict: Runtime Error

// g++ -std=c++14 test.cpp -o test.out
// 問題URL
// https://atcoder.jp/contests/agc047/tasks/agc047_a

// 参考：https://maspypy.com/atcoder-%E5%8F%82%E5%8A%A0%E6%84%9F%E6%83%B3-2020-08-09agc047
//      https://www.hamayanhamayan.com/entry/2020/08/10/054247
// 小数をdoubleで受け取った時点で誤差が発生する、ということが考えられる。
//    →string型で受け取ると良い
// Double型の変数で、例えば整数部4桁、小数部9桁の数を10倍してlongに変換する時、
// そのままx = y*10000000000などとやると誤差のせいでうまくいかないこともある
// Double型変数を一度文字列に変換、それをlongに直してやる必要がある

#include <algorithm>
#include <bitset>
#include <cassert>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits.h>
#include <map>
#include <math.h>
#include <queue>
#include <set>
#include <stack>
#include <stdlib.h>
#include <string.h>
#include <unordered_map>
#include <utility>
#include <vector>
using namespace std;

#define LL long long int
const LL INF = (1LL << 60);
const int INF_INT = 2147483647 - 1e6 - 1;
const LL mod = 1000000007ll;
const int mod_int = 1000000007;

LL N;
LL A[200000];

LL ans = 0;

// xがdivisorを何個約数に持つかを返す
LL numof_divisor(LL x, LL divisor) {
  if (x == 0)
    return 0;
  for (LL i = 0;; i++) {
    if (x % divisor == 0) {
      x /= divisor;
    } else
      return i;
  }
}

void solve() {
  // 集合Aのうち、約数として2をi個、5をj個持つような数の個数をdiv25[i][j]とする
  vector<vector<LL>> div25(19, vector<LL>(19, 0));
  for (int i = 0; i < N; i++) {
    LL d2 = min(18LL, numof_divisor(A[i], 2));
    LL d5 = min(18LL, numof_divisor(A[i], 5));
    div25[d2][d5]++;
  }
  for (int i = 0; i < N; i++) {
    LL d2 = min(18LL, numof_divisor(A[i], 2));
    LL d5 = min(18LL, numof_divisor(A[i], 5));
    for (int i = 18 - d2; i <= 18; i++) {
      for (int j = 18 - d5; j <= 18; j++) {
        ans += div25[i][j];
        if (i == d2 && j == d5)
          ans--;
      }
    }
  }
  ans /= 2;
}

int main() {
  cin >> N;
  for (int i = 0; i < N; i++) {
    string s;
    cin >> s;
    A[i] = 0;
    bool rest_flag = false;
    int rest = 9;
    for (int j = 0; j < s.size(); j++) {
      if (s[j] == '.')
        rest_flag = true;
      else {
        A[i] = A[i] * 10LL + (s[j] - '0');
        if (rest_flag)
          rest--;
      }
    }
    for (int j = 0; j < rest; j++)
      A[i] *= 10LL;
  }

  solve();

  cout << ans << endl;
  return 0;
}

Error: 0

Fixed submission:

// g++ -std=c++14 test.cpp -o test.out
// 問題URL
// https://atcoder.jp/contests/agc047/tasks/agc047_a

// 参考：https://maspypy.com/atcoder-%E5%8F%82%E5%8A%A0%E6%84%9F%E6%83%B3-2020-08-09agc047
//      https://www.hamayanhamayan.com/entry/2020/08/10/054247
// 小数をdoubleで受け取った時点で誤差が発生する、ということが考えられる。
//    →string型で受け取ると良い
// Double型の変数で、例えば整数部4桁、小数部9桁の数を10倍してlongに変換する時、
// そのままx = y*10000000000などとやると誤差のせいでうまくいかないこともある
// Double型変数を一度文字列に変換、それをlongに直してやる必要がある

#include <algorithm>
#include <bitset>
#include <cassert>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits.h>
#include <map>
#include <math.h>
#include <queue>
#include <set>
#include <stack>
#include <stdlib.h>
#include <string.h>
#include <unordered_map>
#include <utility>
#include <vector>
using namespace std;

#define LL long long int
const LL INF = (1LL << 60);
const int INF_INT = 2147483647 - 1e6 - 1;
const LL mod = 1000000007ll;
const int mod_int = 1000000007;

LL N;
LL A[200000];

LL ans = 0;

// xがdivisorを何個約数に持つかを返す
LL numof_divisor(LL x, LL divisor) {
  if (x == 0)
    return 0;
  for (LL i = 0;; i++) {
    if (x % divisor == 0) {
      x /= divisor;
    } else
      return i;
  }
}

void solve() {
  // 集合Aのうち、約数として2をi個、5をj個持つような数の個数をdiv25[i][j]とする
  vector<vector<LL>> div25(19, vector<LL>(19, 0));
  for (int i = 0; i < N; i++) {
    LL d2 = numof_divisor(A[i], 2);
    LL d5 = numof_divisor(A[i], 5);
    div25[d2][d5]++;
  }
  for (int i = 0; i < N; i++) {
    LL d2 = min(18LL, numof_divisor(A[i], 2));
    LL d5 = min(18LL, numof_divisor(A[i], 5));
    for (int i = 18 - d2; i <= 18; i++) {
      for (int j = 18 - d5; j <= 18; j++) {
        ans += div25[i][j];
        if (i == d2 && j == d5)
          ans--;
      }
    }
  }
  ans /= 2;
}

int main() {
  cin >> N;
  for (int i = 0; i < N; i++) {
    string s;
    cin >> s;
    A[i] = 0;
    bool rest_flag = false;
    int rest = 9;
    for (int j = 0; j < s.size(); j++) {
      if (s[j] == '.')
        rest_flag = true;
      else {
        A[i] = A[i] * 10LL + (s[j] - '0');
        if (rest_flag)
          rest--;
      }
    }
    for (int j = 0; j < rest; j++)
      A[i] *= 10LL;
  }

  solve();

  cout << ans << endl;
  return 0;
}