Problem p02609 (C++)

Buggy submission (status: Runtime Error):
#include <iostream>
#include <string>
#include <vector>

int main() {
  int n;
  int sum = 0;
  std::string S;
  std::cin >> n >> S;
  for (int i = 0; i < n; i++) {
    if (S[i] == '1')
      sum++;
  }

  // 例外処理
  if (sum == 0) {
    for (int i = 0; i < n; i++) {
      std::cout << 1 << std::endl;
    }
    return 0;
  }

  // 2^iの剰余
  std::vector<int> count_p1(n), count_m1(n);
  count_p1[0] = 1 % (sum + 1);
  count_m1[0] = 1 % (sum - 1);
  for (int i = 1; i < n; i++) {
    count_p1[i] = (count_p1[i - 1] * 2) % (sum + 1);
    if (sum != 1)
      count_m1[i] = (count_m1[i - 1] * 2) % (sum - 1);
  }

  // Xに対して事前の剰余計算
  int r_p1 = 0, r_m1 = 0;
  for (int i = 0; i < n; i++) {
    if (S[i] == '1') {
      r_p1 += count_p1[n - 1 - i];
      if (sum != 1)
        r_m1 += count_m1[n - 1 - i];
      r_p1 %= sum + 1;
      if (sum != 1)
        r_m1 %= sum - 1;
    }
  }

  // 後は愚直に
  for (int i = 0; i < n; i++) {
    int r = 0;
    if (S[i] == '1') {
      if (sum == 1) {
        std::cout << 0 << std::endl;
        continue;
      }
      // sum - 1の剰余で, 2^(n - 1- i)桁目が消える
      r = r_m1;
      r -= count_m1[n - 1 - i];
      while (r < 0) {
        r += sum - 1;
      }
    } else {
      r = r_p1;
      r += count_p1[n - 1 - i];
      r %= sum + 1;
    }

    int cnt = 1;
    while (r > 0) {
      // popcountの計算
      int x = r;
      int popcount = 0;
      while (x > 0) {
        if (x % 2 == 1)
          popcount++;
        x /= 2;
      }

      r %= popcount;
      cnt++;
    }

    std::cout << cnt << std::endl;
  }
  return 0;
}


Fixed submission:
#include <iostream>
#include <string>
#include <vector>

int main() {
  int n;
  int sum = 0;
  std::string S;
  std::cin >> n >> S;
  for (int i = 0; i < n; i++) {
    if (S[i] == '1')
      sum++;
  }

  // 例外処理
  if (sum == 0) {
    for (int i = 0; i < n; i++) {
      std::cout << 1 << std::endl;
    }
    return 0;
  }

  // 2^iの剰余
  std::vector<int> count_p1(n), count_m1(n);
  count_p1[0] = 1 % (sum + 1);
  if (sum != 1)
    count_m1[0] = 1 % (sum - 1);
  for (int i = 1; i < n; i++) {
    count_p1[i] = (count_p1[i - 1] * 2) % (sum + 1);
    if (sum != 1)
      count_m1[i] = (count_m1[i - 1] * 2) % (sum - 1);
  }

  // Xに対して事前の剰余計算
  int r_p1 = 0, r_m1 = 0;
  for (int i = 0; i < n; i++) {
    if (S[i] == '1') {
      r_p1 += count_p1[n - 1 - i];
      if (sum != 1)
        r_m1 += count_m1[n - 1 - i];
      r_p1 %= sum + 1;
      if (sum != 1)
        r_m1 %= sum - 1;
    }
  }

  // 後は愚直に
  for (int i = 0; i < n; i++) {
    int r = 0;
    if (S[i] == '1') {
      if (sum == 1) {
        std::cout << 0 << std::endl;
        continue;
      }
      // sum - 1の剰余で, 2^(n - 1- i)桁目が消える
      r = r_m1;
      r -= count_m1[n - 1 - i];
      while (r < 0) {
        r += sum - 1;
      }
    } else {
      r = r_p1;
      r += count_p1[n - 1 - i];
      r %= sum + 1;
    }

    int cnt = 1;
    while (r > 0) {
      // popcountの計算
      int x = r;
      int popcount = 0;
      while (x > 0) {
        if (x % 2 == 1)
          popcount++;
        x /= 2;
      }

      r %= popcount;
      cnt++;
    }

    std::cout << cnt << std::endl;
  }
  return 0;
}