Problem p02609 (C++) — buggy submission, verdict: Time Limit Exceeded

#include <bits/stdc++.h>
using namespace std;
#define _GLIBCXX_DEBUG // これつけるとA[N]でもいいらしい
// for文のマクロ
#define rep(i, n) for (int i = 0; i < (int)(n); i++)
#define mp(a, b) make_pair(a, b)
#define big 1000000007
#define all(a) sort((a).begin(), (a).end()) // ソートのマクロ
#define Re(a) reverse((a).begin(), (a).end())
#define YN(a)                                                                  \\
  if (a) {                                                                     \\
    cout << "Yes" << endl;                                                     \\
  } else                                                                       \\
    cout << "No" << endl; // 条件によってYes、Noを出力する
const int MOD = 1000000007;
const double pi = 3.141592653589793;
// a^n modをO(logN)で計算
long long modpow(long long a, long long n, long long mod) {
  long long res = 1;
  while (n > 0) {
    if (n & 1)
      res = res * a % mod;
    a = a * a % mod;
    n >>= 1;
  }
  return res;
}
// a-bをMODで割ったあまり、負にならない工夫
long long sub(long long a, long long b, int mod) {
  long long ans = ((a % mod) - (b % mod)) % mod;
  if (ans >= 0) {
    return ans;
  } else {
    return ans + mod;
  }
}
int main() {
  int n;
  cin >> n; // n桁の整数x
  string x;
  cin >> x;
  bitset<200001> bi(x);
  int dpop = bi.count(); // 最初の1の数
  int64_t NUMp = 0, NUMm = 0;
  // 方針:
  // popcは大した数じゃない(最大2*10^5)から、一回計算すれば整数型としてふつうに計算できる大きさになる
  // 考えないといけないこと:1が1個しかない->そこを反転するとbit=0になって、操作0回で終わる
  // バカでかい数の余りを計算する abc164dを参考
  rep(j, n) {
    NUMp += modpow(2, j, (dpop + 1)) * (bi.test(j)) % (dpop + 1);
    NUMp %= (dpop + 1);
    if (dpop > 1) {
      NUMm += modpow(2, j, (dpop - 1)) * (bi.test(j)) % (dpop - 1);
      NUMm %= (dpop - 1);
    }
  }
  for (int i = n - 1; i >= 0; i--) {
    int cnt = 0;
    int popc;
    int64_t num;
    if (dpop == 1 && bi.test(i)) {
      cout << 0 << endl;
      continue;
    }
    if (bi.test(i)) { // 1を反転する->popc = dpop-1 -> NUMmを使う
      popc = dpop - 1;
      num = sub(NUMm, modpow(2, i, popc), popc);
      num %= popc;
    } else {
      popc = dpop + 1;
      num = NUMp + modpow(2, i, popc);
      num %= popc;
    }
    bi.flip(i);
    auto tmp = bi;
    // cout<<num<<endl;
    cnt = 1;
    while (num != 0) {
      bitset<18> tbdiv(num);
      popc = tbdiv.count();
      num %= popc;
      cnt++;
    }
    cout << cnt << endl;
    bi.flip(i);
  }
}

Error: TLE

Fixed submission:

#include <bits/stdc++.h>
using namespace std;
#define _GLIBCXX_DEBUG // これつけるとA[N]でもいいらしい
// for文のマクロ
#define rep(i, n) for (int i = 0; i < (int)(n); i++)
#define mp(a, b) make_pair(a, b)
#define big 1000000007
#define all(a) sort((a).begin(), (a).end()) // ソートのマクロ
#define Re(a) reverse((a).begin(), (a).end())
#define YN(a)                                                                  \\
  if (a) {                                                                     \\
    cout << "Yes" << endl;                                                     \\
  } else                                                                       \\
    cout << "No" << endl; // 条件によってYes、Noを出力する
const int MOD = 1000000007;
const double pi = 3.141592653589793;
// a^n modをO(logN)で計算
long long modpow(long long a, long long n, long long mod) {
  long long res = 1;
  while (n > 0) {
    if (n & 1)
      res = res * a % mod;
    a = a * a % mod;
    n >>= 1;
  }
  return res;
}
// a-bをMODで割ったあまり、負にならない工夫
long long sub(long long a, long long b, int mod) {
  long long ans = ((a % mod) - (b % mod)) % mod;
  if (ans >= 0) {
    return ans;
  } else {
    return ans + mod;
  }
}
int main() {
  int n;
  cin >> n; // n桁の整数x
  string x;
  cin >> x;
  bitset<200001> bi(x);
  int dpop = bi.count(); // 最初の1の数
  int64_t NUMp = 0, NUMm = 0;
  // 方針:
  // popcは大した数じゃないから、一回計算すれば整数型としてふつうに計算できる大きさになる
  // 考えないといけないこと:1が1個しかない->そこを反転するとbit=0になって、操作0回で終わる
  // バカでかい数の余りを計算する abc164dを参考
  rep(j, n) {
    NUMp += modpow(2, j, (dpop + 1)) * (bi.test(j)) % (dpop + 1);
    NUMp %= (dpop + 1);
    if (dpop > 1) {
      NUMm += modpow(2, j, (dpop - 1)) * (bi.test(j)) % (dpop - 1);
      NUMm %= (dpop - 1);
    }
  }
  for (int i = n - 1; i >= 0; i--) {
    int cnt = 0;
    int popc;
    int64_t num;
    if (dpop == 1 && bi.test(i)) {
      cout << 0 << endl;
      continue;
    }
    if (bi.test(i)) { // 1を反転する->popc = dpop-1 -> NUMmを使う
      popc = dpop - 1;
      num = sub(NUMm, modpow(2, i, popc), popc);
      num %= popc;
    } else {
      popc = dpop + 1;
      num = NUMp + modpow(2, i, popc);
      num %= popc;
    }
    bi.flip(i);
    auto tmp = bi;
    // cout<<num<<endl;
    cnt = 1;
    while (num != 0) {
      bitset<200001> tbdiv(num);
      popc = tbdiv.count();
      num %= popc;
      cnt++;
    }
    cout << cnt << endl;
    bi.flip(i);
  }
}