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

#include <bits/stdc++.h>
using namespace std;
using lint = long int;

int N;
string X;

/*2進数表記を10進数表記に直しmで割った際の剰余*/
lint convert_stoi_mod(string &S, int n, int m) {
  if (m == 0)
    return 0; // 法が0⇒1のbitは存在しない
  lint res = 0, p = 1;
  for (int i = n; i > 0; i--) {
    if (S[i - 1] == '1') {
      res += p;
      res %= m;
    }
    p *= 2;
    p %= m;
  }

  return res;
}

/*2分累乗法：剰余計算*/
lint binary_pow(lint a, lint n, lint m) {
  if (m == 0)
    return 0; // 法が0⇒1のbitが存在しない

  lint res = 1;
  while (n > 0) {
    if (n & 1)
      res = (res * a) % m;
    a = (a * a) % m;
    n >>= 1;
  }

  return res;
}

/*2進数表記の文字列についての1のビット数*/
lint pop_count_str(string &S, lint n) {
  lint cn = 0;
  for (int i = 0; i < n; i++) {
    if (S[i] == '1')
      ++cn;
  }
  return cn;
}

/*long int型整数の2進数表記における1のビット数*/
lint pop_count_int(lint X) {
  lint cn = 0;
  while (X > 0) {
    if (X & 1)
      ++cn;
    X /= 2;
  }
  return cn;
}

/*modを法として,valを合同な最小の非負正数に修正*/
void equiv(lint &val, lint mod) {
  if (mod == 0)
    return; // 法が0⇒1のbitなし⇒valは0⇒変更なし

  if (val < 0)
    val += mod;
  else if (val >= mod)
    val %= mod;
}

/*当該問題の関数*/
lint f(lint X) {
  if (X == 0)
    return 1;

  lint cn = pop_count_int(X);
  lint X_next = X % cn;
  return 1 + f(X_next);
}

/*Xに対応する整数値のみ莫大な値となるので別途計算することを念頭に...*/
int main() {
  cin >> N >> X;

  lint bit_count = pop_count_str(X, N); // Xの2進表記における1のビット数

  /*ビットは1増えるか減るか...従って対応する法計算結果を先に取得*/
  lint dNp1 = convert_stoi_mod(X, N, bit_count + 1);
  lint dNm1 = convert_stoi_mod(X, N, bit_count - 1);

  lint X_tmp = 0;
  bool no_existence_1bit = false;
  for (int i = 0; i < N; i++) {
    if (X[i] == '1') {
      /*同じ法で変更ビットに相当する値の修正...1 to 0*/
      if (bit_count == 1)
        no_existence_1bit = true;
      X_tmp = dNm1 - binary_pow(2, N - 1 - i, bit_count - 1);
      equiv(X_tmp, bit_count - 1);
    } else if (X[i] == '0') {
      /*同様...ただし法は異なる...0 to 1*/
      X_tmp = dNp1 + binary_pow(2, N - 1 - i, bit_count + 1);
      equiv(X_tmp, bit_count + 1);
    }

    if (no_existence_1bit) {
      cout << 0 << endl;
      no_existence_1bit = false;
    } else
      cout << f(X_tmp) << endl;
  }

  return 0;
}

Error: 0

Fixed submission:

#include <bits/stdc++.h>
using namespace std;
using lint = long int;

int N;
string X;

/*2進数表記を10進数表記に直しmで割った際の剰余*/
lint convert_stoi_mod(string &S, int n, int m) {
  lint res = 0, p = 1;
  for (int i = n; i > 0; i--) {
    if (S[i - 1] == '1') {
      res += p;
      res %= m;
    }
    p *= 2;
    p %= m;
  }

  return res;
}

/*2分累乗法：剰余計算...計算量O(logN)*/
lint binary_pow(lint a, lint n, lint m) {
  lint res = 1;

  while (n > 0) {
    if (n & 1)
      res = (res * a) % m;
    a = (a * a) % m;
    n >>= 1;
  }

  return res;
}

/*2進数表記の文字列についての1のビット数*/
lint pop_count_str(string &S, lint n) {
  lint cn = 0;
  for (int i = 0; i < n; i++) {
    if (S[i] == '1')
      ++cn;
  }
  return cn;
}

/*long int型整数の2進数表記における1のビット数*/
lint pop_count_int(lint X) {
  lint cn = 0;
  while (X > 0) {
    if (X & 1)
      ++cn;
    X /= 2;
  }
  return cn;
}

/*modを法として,valを合同な最小の非負正数に修正*/
void equiv(lint &val, lint mod) {
  if (val < 0)
    val += mod;
  else if (val >= mod)
    val %= mod;
}

/*当該問題の関数*/
lint f(lint X) {
  if (X == 0)
    return 1;

  lint cn = pop_count_int(X);
  lint X_next = X % cn;
  return 1 + f(X_next);
}

/*Xに対応する整数値のみ莫大な値となるので別途計算することを念頭に...*/
int main() {
  cin >> N >> X;

  lint bit_count = pop_count_str(X, N); // Xの2進表記における1のビット数

  /*ビットは1増えるか減るか...従って対応する法計算結果を先に取得*/
  lint dNp1 = convert_stoi_mod(X, N, bit_count + 1);
  lint dNm1 = convert_stoi_mod(X, N, bit_count - 1);

  lint X_tmp = 0;
  for (int i = 0; i < N; i++) { // o(NlogN)
    if (X[i] == '1') {
      /*同じ法で変更ビットに相当する値の修正...1 to 0*/
      X_tmp = dNm1 - binary_pow(2, N - 1 - i, bit_count - 1); // O(logN)
      equiv(X_tmp, bit_count - 1);
    } else if (X[i] == '0') {
      /*同様...ただし法は異なる...0 to 1*/
      X_tmp = dNp1 + binary_pow(2, N - 1 - i, bit_count + 1); // O(logN)
      equiv(X_tmp, bit_count + 1);
    }

    cout << f(X_tmp) << endl;
  }

  return 0;
}