Problem p03298 (C++)

Buggy submission (status: Time Limit Exceeded):
#include <algorithm>
#include <bitset>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <fstream>
#include <functional>
#include <iomanip>
#include <iostream>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <sstream>
#include <stack>
#include <stdexcept>
#include <string>
#include <utility>
#include <vector>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
#define MEM(a, b) memset((a), (b), sizeof(a))
const LL INF = 1e9 + 7;
const int N = 1e6 + 10;
int a[N];
int b[N];
int c[N];
int d[N];
int flag[N];
int p[N];
int cnt[N];
void init() {
  for (int i = 1; i < N; i++) {
    cnt[i] = cnt[i >> 1] + (i & 1);
  }
}
void check(string &str, int a[], int base, int mod, int flag) {
  int sz = (str.length());
  int tot = 1 << sz;
  for (int o = 0; o < tot; o++) {
    int s1 = 0;
    int s2 = 0;
    int cur = 0;
    if (flag == 2)
      cur = cnt[o];
    for (int i = 0; i < sz; i++) {
      if (o >> i & 1)
        s1 = (1LL * s1 * base + str[i]) % mod;
      else
        s2 = (s2 + 1LL * p[cur++] * str[i]) % mod;
    }
    if (flag == 1)
      s1 = 1LL * s1 * p[sz - cnt[o]] % mod;
    a[o] = s1 - s2;
    if (a[o] < 0)
      a[o] += mod;
  }
}
vector<pair<int, int>> v[20];
int main() {
  // freopen("input.txt", "r", stdin);
  // freopen("output.txt", "w", stdout);
  string str;
  int n;
  cin >> n;
  cin >> str;
  string s1 = str.substr(0, n);
  string s2 = str.substr(n);
  int mod1 = 99997897;
  int mod2 = 99998111;
  init();
  p[0] = 1;
  for (int i = 1; i < 20; i++)
    p[i] = p[i - 1] * 131LL % mod1;
  check(s1, a, 131, mod1, 1);
  check(s2, b, 131, mod1, 2);
  for (int i = 1; i < 20; i++)
    p[i] = p[i - 1] * 131LL % mod2;
  check(s1, c, 131, mod2, 1);
  check(s2, d, 131, mod2, 2);
  for (int i = 0; i < (1 << n); i++) {
    v[cnt[i]].push_back({(mod1 - b[i]) % mod1, (mod2 - d[i]) % mod2});
  }
  for (int i = 0; i < 20; i++) {
    if (v[i].empty())
      continue;
    sort(v[i].begin(), v[i].end());
  }
  LL ans = 0;
  for (int i = 0; i < (1 << n); i++) {
    auto p = make_pair(a[i], c[i]);
    auto vv = v[n - cnt[i]];
    ans += upper_bound(vv.begin(), vv.end(), p) -
           lower_bound(vv.begin(), vv.end(), p);
  }
  printf("%lld\n", ans);
  return 0;
}

Fixed submission:
#include <algorithm>
#include <bitset>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <fstream>
#include <functional>
#include <iomanip>
#include <iostream>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <sstream>
#include <stack>
#include <stdexcept>
#include <string>
#include <utility>
#include <vector>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
#define MEM(a, b) memset((a), (b), sizeof(a))
const LL INF = 1e9 + 7;
const int N = 1e6 + 10;
int a[N];
int b[N];
int c[N];
int d[N];
int flag[N];
int p[N];
int cnt[N];
void init() {
  for (int i = 1; i < N; i++) {
    cnt[i] = cnt[i >> 1] + (i & 1);
  }
}
void check(string &str, int a[], int base, int mod, int flag) {
  int sz = (str.length());
  int tot = 1 << sz;
  for (int o = 0; o < tot; o++) {
    int s1 = 0;
    int s2 = 0;
    int cur = 0;
    if (flag == 2)
      cur = cnt[o];
    for (int i = 0; i < sz; i++) {
      if (o >> i & 1)
        s1 = (1LL * s1 * base + str[i]) % mod;
      else
        s2 = (s2 + 1LL * p[cur++] * str[i]) % mod;
    }
    if (flag == 1)
      s1 = 1LL * s1 * p[sz - cnt[o]] % mod;
    a[o] = s1 - s2;
    if (a[o] < 0)
      a[o] += mod;
  }
}
vector<pair<int, int>> v[20];
int main() {
  // freopen("input.txt", "r", stdin);
  // freopen("output.txt", "w", stdout);
  string str;
  int n;
  cin >> n;
  cin >> str;
  string s1 = str.substr(0, n);
  string s2 = str.substr(n);
  int mod1 = 99997897;
  int mod2 = 99998111;
  init();
  p[0] = 1;
  for (int i = 1; i < 20; i++)
    p[i] = p[i - 1] * 131LL % mod1;
  check(s1, a, 131, mod1, 1);
  check(s2, b, 131, mod1, 2);
  for (int i = 1; i < 20; i++)
    p[i] = p[i - 1] * 131LL % mod2;
  check(s1, c, 131, mod2, 1);
  check(s2, d, 131, mod2, 2);
  for (int i = 0; i < (1 << n); i++) {
    v[cnt[i]].push_back({(mod1 - b[i]) % mod1, (mod2 - d[i]) % mod2});
  }
  for (int i = 0; i < 20; i++) {
    if (v[i].empty())
      continue;
    sort(v[i].begin(), v[i].end());
  }
  LL ans = 0;
  for (int i = 0; i < (1 << n); i++) {
    auto p = make_pair(a[i], c[i]);
    auto &vv = v[n - cnt[i]];
    ans += upper_bound(vv.begin(), vv.end(), p) -
           lower_bound(vv.begin(), vv.end(), p);
  }
  printf("%lld\n", ans);
  return 0;
}