Problem p02816 (C++)

Buggy submission (status: Runtime Error):
// #undef _DEBUG
// #pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace std::chrono;
#define int long long // todo 消したら動かない intの代わりにsignedを使う
#define ll long long
auto start_time = system_clock::now();
auto past_time = system_clock::now();

#define debugName(VariableName) #VariableName
// 最大引数がN
#define over2(o1, o2, name, ...) name
#define over3(o1, o2, o3, name, ...) name
#define over4(o1, o2, o3, o4, name, ...) name
#define over5(o1, o2, o3, o4, o5, name, ...) name
#define over6(o1, o2, o3, o4, o5, o6, name, ...) name
#define over7(o1, o2, o3, o4, o5, o6, o7, name, ...) name
#define over8(o1, o2, o3, o4, o5, o6, o7, o8, name, ...) name
#define over9(o1, o2, o3, o4, o5, o6, o7, o8, o9, name, ...) name
#define over10(o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, name, ...) name

#define rep(i, a, b) for (int i = a; i < b; i++)
#define rrep(i, a, b) for (int i = a; i >= b; i--)
#define fore(i, a) for (auto &i : a)
#define all(x) (x).begin(), (x).end()

#define rand xor128_
/*@formatter:on*/
unsigned long xor128_(void) {
  static unsigned long x = 123456789, y = 362436069, z = 521288629,
                       w = 88675123;
  unsigned long t;
  t = (x ^ (x << 11));
  x = y;
  y = z;
  z = w;
  return (w = (w ^ (w >> 19)) ^ (t ^ (t >> 8)));
}
/*@formatter:on*/
ll rand(ll min, ll max) {
  assert(min <= max);
  if (min >= 0 && max >= 0) {
    return rand() % (max + 1 - min) + min;
  } else if (max < 0) {
    return -rand(-max, -min);
  } else {
    if (rand() % 2) {
      return rand(0, max);
    } else {
      return -rand(0, -min);
    }
  }
}
#define sz(a) ((int)a.size())
const int inf = (int)1e9 + 100;

/*@formatter:off*/
//@起動時
struct initon {
  initon() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    cout.setf(ios::fixed);
    cout.precision(16);
    srand((unsigned)clock() + (unsigned)time(NULL));
  };
} initonv;
#define pre prev
#define nex next

// hashを共有したくない場合、中に書く
const uint64_t base = rand((uint64_t)868491463, ((uint64_t)1 << 61) - 1 - 1);

// 安全で爆速なrollinghash
class roll {
  /*@formatter:on*/
  static constexpr uint64_t mask30 = ((uint64_t)1 << 30) - 1;
  static constexpr uint64_t mask31 = ((uint64_t)1 << 31) - 1;
  static constexpr uint64_t mask61 = ((uint64_t)1 << 61) - 1;
  static constexpr uint64_t offset = mask61 * 7;
  static constexpr uint64_t mod(const uint64_t x) {
    const uint64_t y = (x >> 61) + (x & mask61);
    return y >= mask61 ? y - mask61 : y;
  }
  static constexpr uint64_t mul(const uint64_t x, const uint64_t y) {
    const uint64_t xh = x >> 31, xl = x & mask31;
    const uint64_t yh = y >> 31, yl = y & mask31;
    const uint64_t z = xl * yh + xh * yl;
    const uint64_t zh = z >> 30, zl = z & mask30;
    return xh * yh * 2 + zh + (zl << 31) + xl * yl;
  }
  const std::size_t siz;
  vector<uint64_t> pow, h;

public:
  template <typename T>
  roll(T &A) : siz(sz(A)), pow(siz + 1, 1), h(siz + 1, 0) {
    for (std::size_t i = 1; i <= siz; i++) {
      pow[i] = mod(mul(pow[i - 1], base)),
      h[i] = mod(mul(h[i - 1], base) + A[i - 1]);
    }
  }
  uint64_t operator()(const std::size_t l, const std::size_t r) {
    return mod(h[r] + offset - mul(h[l], pow[r - l]));
  }
  uint64_t operator()(int r = inf) { return operator()(0, min((int)siz, r)); }
  // get lcp of S[a:] and T[b:]
  // 接頭語がどれだけ一致するか
  // 範囲の重複を含む
  int lcp_dup(int a, int b) {
    int len = min((int)siz - a, (int)siz - b);
    int low = 0, high = len;
    while (high - low > 1) {
      int mid = (low + high) >> 1;
      if (operator()(a, a + mid) != operator()(b, b + mid))
        high = mid;
      else
        low = mid;
    }
    return low;
  }
  // 重複を認めない
  int lcp_not(int a, int b) {
    return min(lcp_dup(a, b), b - a);
  } //@formatter:on
};
// 動かない場合roll2
// roll ro(list);
//---------------------------------------------------------------------------------------------------
template <int MOD> struct ModInt {
  static const int Mod = MOD;
  unsigned x;
  ModInt() : x(0) {}
  ModInt(signed sig) { x = sig < 0 ? sig % MOD + MOD : sig % MOD; }
  ModInt(signed long long sig) { x = sig < 0 ? sig % MOD + MOD : sig % MOD; }
  int get() const { return (int)x; }
  ModInt &operator+=(ModInt that) {
    if ((x += that.x) >= MOD)
      x -= MOD;
    return *this;
  }
  ModInt &operator-=(ModInt that) {
    if ((x += MOD - that.x) >= MOD)
      x -= MOD;
    return *this;
  }
  ModInt &operator*=(ModInt that) {
    x = (unsigned long long)x * that.x % MOD;
    return *this;
  }
  ModInt &operator/=(ModInt that) { return *this *= that.inverse(); }
  ModInt operator+(ModInt that) const { return ModInt(*this) += that; }
  ModInt operator-(ModInt that) const { return ModInt(*this) -= that; }
  ModInt operator*(ModInt that) const { return ModInt(*this) *= that; }
  ModInt operator/(ModInt that) const { return ModInt(*this) /= that; }
  ModInt inverse() const {
    long long a = x, b = MOD, u = 1, v = 0;
    while (b) {
      long long t = a / b;
      a -= t * b;
      std::swap(a, b);
      u -= t * v;
      std::swap(u, v);
    }
    return ModInt(u);
  }
  bool operator==(ModInt that) const { return x == that.x; }
  bool operator!=(ModInt that) const { return x != that.x; }
  ModInt operator-() const {
    ModInt t;
    t.x = x == 0 ? 0 : Mod - x;
    return t;
  }
};
template <int MOD> ModInt<MOD> operator^(ModInt<MOD> a, unsigned long long k) {
  ModInt<MOD> r = 1;
  while (k) {
    if (k & 1)
      r *= a;
    a *= a;
    k >>= 1;
  }
  return r;
}
int getrandmax() {
  static uint32_t y = time(NULL);
  y ^= (y << 13);
  y ^= (y >> 17);
  y ^= (y << 5);
  return abs((int)y);
}
int getrand(int l, int r) { // [l, r]
  return getrandmax() % (r - l + 1) + l;
}
typedef ModInt<1000000007> mint1;
typedef ModInt<1000000009> mint2;
int primes[10] = {10007, 10009, 10037, 10039, 10061,
                  10067, 10069, 10079, 10091, 10093};
bool isShuffle = false;
struct RollingHash {
  mint1 p1;
  mint2 p2;
  int n;
  vector<mint1> m1;
  vector<mint2> m2;
  vector<mint1> v1;
  vector<mint2> v2;

  RollingHash() {
    if (!isShuffle) {
      rep(i, 0, 101) {
        int a = getrand(0, 9);
        int b = getrand(0, 9);
        swap(primes[a], primes[b]);
      }
      isShuffle = true;
    }
    p1 = primes[0], p2 = primes[1];
  }

  void init(string s, char o = 'a') {
    vector<int> v;
    fore(c, s) v.push_back(c - o);
    init(v);
  }

  void init(vector<int> s) {
    n = s.size();
    m1.resize(n);
    m2.resize(n);
    v1.resize(n);
    v2.resize(n);

    m1[0] = 1;
    m2[0] = 1;
    v1[0] = s[0];
    v2[0] = s[0];

    rep(i, 1, n) {
      m1[i] = m1[i - 1] * p1;
      m2[i] = m2[i - 1] * p2;
      v1[i] = v1[i - 1] + m1[i] * s[i];
      v2[i] = v2[i - 1] + m2[i] * s[i];
    }
  }
  inline pair<mint1, mint2> hash(int l, int r) { // s[l..r]
    assert(l <= r);
    assert(r < n);
    mint1 a = v1[r];
    if (l)
      a -= v1[l - 1];
    a *= m1[n - 1 - r];

    mint2 b = v2[r];
    if (l)
      b -= v2[l - 1];
    b *= m2[n - 1 - r];

    return {a, b};
  }
  inline ll llhash(int l, int r) { // s[l..r]
    auto h = hash(l, r);
    return 1LL * h.first.get() * h.second.Mod + h.second.get();
  }
};

using vi = vector<int>;
int N;

void solve() {
  cin >> N;
  vi A(N), B(N), A2(N), B2(N);
  rep(i, 0, N) cin >> A[i];
  rep(i, 0, N) cin >> B[i];

  rep(i, 0, N) A2[i] = A[i] ^ A[(i + 1) % N];
  rep(i, 0, N) B2[i] = B[i] ^ B[(i + 1) % N];

  vector<int> v;
  rep(i, 0, N) v.push_back(A2[i]);
  rep(i, 0, N) v.push_back(A2[i]);
  rep(i, 0, N) v.push_back(B2[i]);

  RollingHash rh;
  rh.init(v);
  rep(k, 0, N) if (rh.hash(k, k + N) == rh.hash(N * 2, N * 2 + N)) {
    int x = A[k] ^ B[0];
    cout << k << " " << x << endl;
  }
}

auto my(ll n, vi &a) { return 0; }

auto sister(ll n, vi &a) {
  ll ret = 0;
  return ret;
}

signed main() {
  solve();
  return 0;
};


Fixed submission:
// #undef _DEBUG
// #pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace std::chrono;
#define int long long // todo 消したら動かない intの代わりにsignedを使う
#define ll long long
auto start_time = system_clock::now();
auto past_time = system_clock::now();

#define debugName(VariableName) #VariableName
// 最大引数がN
#define over2(o1, o2, name, ...) name
#define over3(o1, o2, o3, name, ...) name
#define over4(o1, o2, o3, o4, name, ...) name
#define over5(o1, o2, o3, o4, o5, name, ...) name
#define over6(o1, o2, o3, o4, o5, o6, name, ...) name
#define over7(o1, o2, o3, o4, o5, o6, o7, name, ...) name
#define over8(o1, o2, o3, o4, o5, o6, o7, o8, name, ...) name
#define over9(o1, o2, o3, o4, o5, o6, o7, o8, o9, name, ...) name
#define over10(o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, name, ...) name

#define rep(i, a, b) for (int i = a; i < b; i++)
#define rrep(i, a, b) for (int i = a; i >= b; i--)
#define fore(i, a) for (auto &i : a)
#define all(x) (x).begin(), (x).end()

#define rand xor128_
/*@formatter:on*/
unsigned long xor128_(void) {
  static unsigned long x = 123456789, y = 362436069, z = 521288629,
                       w = 88675123;
  unsigned long t;
  t = (x ^ (x << 11));
  x = y;
  y = z;
  z = w;
  return (w = (w ^ (w >> 19)) ^ (t ^ (t >> 8)));
}
/*@formatter:on*/
ll rand(ll min, ll max) {
  assert(min <= max);
  if (min >= 0 && max >= 0) {
    return rand() % (max + 1 - min) + min;
  } else if (max < 0) {
    return -rand(-max, -min);
  } else {
    if (rand() % 2) {
      return rand(0, max);
    } else {
      return -rand(0, -min);
    }
  }
}
#define sz(a) ((int)a.size())
const int inf = (int)1e9 + 100;

/*@formatter:off*/
//@起動時
struct initon {
  initon() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    cout.setf(ios::fixed);
    cout.precision(16);
    srand((unsigned)clock() + (unsigned)time(NULL));
  };
} initonv;
#define pre prev
#define nex next

// hashを共有したくない場合、中に書く
const uint64_t base = rand((uint64_t)868491463, ((uint64_t)1 << 61) - 1 - 1);

// 安全で爆速なrollinghash
class roll {
  /*@formatter:on*/
  static constexpr uint64_t mask30 = ((uint64_t)1 << 30) - 1;
  static constexpr uint64_t mask31 = ((uint64_t)1 << 31) - 1;
  static constexpr uint64_t mask61 = ((uint64_t)1 << 61) - 1;
  static constexpr uint64_t offset = mask61 * 7;
  static constexpr uint64_t mod(const uint64_t x) {
    const uint64_t y = (x >> 61) + (x & mask61);
    return y >= mask61 ? y - mask61 : y;
  }
  static constexpr uint64_t mul(const uint64_t x, const uint64_t y) {
    const uint64_t xh = x >> 31, xl = x & mask31;
    const uint64_t yh = y >> 31, yl = y & mask31;
    const uint64_t z = xl * yh + xh * yl;
    const uint64_t zh = z >> 30, zl = z & mask30;
    return xh * yh * 2 + zh + (zl << 31) + xl * yl;
  }
  const std::size_t siz;
  vector<uint64_t> pow, h;

public:
  template <typename T>
  roll(T &A) : siz(sz(A)), pow(siz + 1, 1), h(siz + 1, 0) {
    for (std::size_t i = 1; i <= siz; i++) {
      pow[i] = mod(mul(pow[i - 1], base)),
      h[i] = mod(mul(h[i - 1], base) + A[i - 1]);
    }
  }
  uint64_t operator()(const std::size_t l, const std::size_t r) {
    return mod(h[r] + offset - mul(h[l], pow[r - l]));
  }
  uint64_t operator()(int r = inf) { return operator()(0, min((int)siz, r)); }
  // get lcp of S[a:] and T[b:]
  // 接頭語がどれだけ一致するか
  // 範囲の重複を含む
  int lcp_dup(int a, int b) {
    int len = min((int)siz - a, (int)siz - b);
    int low = 0, high = len;
    while (high - low > 1) {
      int mid = (low + high) >> 1;
      if (operator()(a, a + mid) != operator()(b, b + mid))
        high = mid;
      else
        low = mid;
    }
    return low;
  }
  // 重複を認めない
  int lcp_not(int a, int b) {
    return min(lcp_dup(a, b), b - a);
  } //@formatter:on
};
// 動かない場合roll2
// roll ro(list);
//---------------------------------------------------------------------------------------------------
template <int MOD> struct ModInt {
  static const int Mod = MOD;
  unsigned x;
  ModInt() : x(0) {}
  ModInt(signed sig) { x = sig < 0 ? sig % MOD + MOD : sig % MOD; }
  ModInt(signed long long sig) { x = sig < 0 ? sig % MOD + MOD : sig % MOD; }
  int get() const { return (int)x; }
  ModInt &operator+=(ModInt that) {
    if ((x += that.x) >= MOD)
      x -= MOD;
    return *this;
  }
  ModInt &operator-=(ModInt that) {
    if ((x += MOD - that.x) >= MOD)
      x -= MOD;
    return *this;
  }
  ModInt &operator*=(ModInt that) {
    x = (unsigned long long)x * that.x % MOD;
    return *this;
  }
  ModInt &operator/=(ModInt that) { return *this *= that.inverse(); }
  ModInt operator+(ModInt that) const { return ModInt(*this) += that; }
  ModInt operator-(ModInt that) const { return ModInt(*this) -= that; }
  ModInt operator*(ModInt that) const { return ModInt(*this) *= that; }
  ModInt operator/(ModInt that) const { return ModInt(*this) /= that; }
  ModInt inverse() const {
    long long a = x, b = MOD, u = 1, v = 0;
    while (b) {
      long long t = a / b;
      a -= t * b;
      std::swap(a, b);
      u -= t * v;
      std::swap(u, v);
    }
    return ModInt(u);
  }
  bool operator==(ModInt that) const { return x == that.x; }
  bool operator!=(ModInt that) const { return x != that.x; }
  ModInt operator-() const {
    ModInt t;
    t.x = x == 0 ? 0 : Mod - x;
    return t;
  }
};
template <int MOD> ModInt<MOD> operator^(ModInt<MOD> a, unsigned long long k) {
  ModInt<MOD> r = 1;
  while (k) {
    if (k & 1)
      r *= a;
    a *= a;
    k >>= 1;
  }
  return r;
}
int getrandmax() {
  static uint32_t y = time(NULL);
  y ^= (y << 13);
  y ^= (y >> 17);
  y ^= (y << 5);
  return abs((int)y);
}
int getrand(int l, int r) { // [l, r]
  return getrandmax() % (r - l + 1) + l;
}
typedef ModInt<1000000007> mint1;
typedef ModInt<1000000009> mint2;
int primes[10] = {10007, 10009, 10037, 10039, 10061,
                  10067, 10069, 10079, 10091, 10093};
bool isShuffle = false;
struct RollingHash {
  mint1 p1;
  mint2 p2;
  int n;
  vector<mint1> m1;
  vector<mint2> m2;
  vector<mint1> v1;
  vector<mint2> v2;

  RollingHash() {
    if (!isShuffle) {
      rep(i, 0, 101) {
        int a = getrand(0, 9);
        int b = getrand(0, 9);
        swap(primes[a], primes[b]);
      }
      isShuffle = true;
    }
    p1 = primes[0], p2 = primes[1];
  }

  void init(string s, char o = 'a') {
    vector<int> v;
    fore(c, s) v.push_back(c - o);
    init(v);
  }

  void init(vector<int> s) {
    n = s.size();
    m1.resize(n);
    m2.resize(n);
    v1.resize(n);
    v2.resize(n);

    m1[0] = 1;
    m2[0] = 1;
    v1[0] = s[0];
    v2[0] = s[0];

    rep(i, 1, n) {
      m1[i] = m1[i - 1] * p1;
      m2[i] = m2[i - 1] * p2;
      v1[i] = v1[i - 1] + m1[i] * s[i];
      v2[i] = v2[i - 1] + m2[i] * s[i];
    }
  }
  inline pair<mint1, mint2> hash(int l, int r) { // s[l..r]
    assert(l <= r);
    assert(r < n);
    mint1 a = v1[r];
    if (l)
      a -= v1[l - 1];
    a *= m1[n - 1 - r];

    mint2 b = v2[r];
    if (l)
      b -= v2[l - 1];
    b *= m2[n - 1 - r];

    return {a, b};
  }
  inline ll llhash(int l, int r) { // s[l..r]
    auto h = hash(l, r);
    return 1LL * h.first.get() * h.second.Mod + h.second.get();
  }
};

using vi = vector<int>;
int N;

void solve() {
  cin >> N;
  vi A(N), B(N), A2(N), B2(N);
  rep(i, 0, N) cin >> A[i];
  rep(i, 0, N) cin >> B[i];

  rep(i, 0, N) A2[i] = A[i] ^ A[(i + 1) % N];
  rep(i, 0, N) B2[i] = B[i] ^ B[(i + 1) % N];

  vector<int> v;
  rep(i, 0, N) v.push_back(A2[i]);
  rep(i, 0, N) v.push_back(A2[i]);
  rep(i, 0, N) v.push_back(B2[i]);

  RollingHash rh;
  rh.init(v);
  rep(k, 0, N) if (rh.hash(k, k + N - 1) == rh.hash(N * 2, N * 2 + N - 1)) {
    int x = A[k] ^ B[0];
    cout << k << " " << x << endl;
  }
}

auto my(ll n, vi &a) { return 0; }

auto sister(ll n, vi &a) {
  ll ret = 0;
  return ret;
}

signed main() {
  solve();
  return 0;
};