cp-library

C++ Library for Competitive Programming

View the Project on GitHub emthrm/cp-library

:heavy_check_mark: 基底 (basis)
(include/emthrm/math/basis.hpp)

仕様

template <int D>
struct Basis;

メンバ変数

名前 説明
std::vector<std::bitset<D>> v ベクトル空間
std::vector<int> msb $i$ 番目のベクトルの最上位ビット

メンバ関数

名前 効果・戻り値
Basis(); デフォルトコンストラクタ
bool add(std::bitset<D> val); ベクトル $\mathrm{val}$ を加えたのち、実際に要素数が増えたかを返す。
int rank() const; 要素数
inline bool operator<(const Basis& x) const;  

参考文献

TODO

Submissons

https://onlinejudge.u-aizu.ac.jp/solutions/problem/2416/review/5214392/emthrm/C++17

Verified with

Code

#ifndef EMTHRM_MATH_BASIS_HPP_
#define EMTHRM_MATH_BASIS_HPP_

#include <algorithm>
#include <bitset>
#include <iterator>
#include <vector>

namespace emthrm {

template <int D>
struct Basis {
  std::vector<std::bitset<D>> v;
  std::vector<int> msb;

  Basis() = default;

  bool add(std::bitset<D> val) {
    const int n = rank();
    if (n == D) return false;
    for (int i = 0; i < n; ++i) {
      if (val[msb[i]]) val ^= v[i];
    }
    if (val.none()) return false;
    int m = D - 1;
    while (!val[m]) --m;
    if (v.empty()) [[unlikely]] {
      v.emplace_back(val);
      msb.emplace_back(m);
      return true;
    }
    const int idx = std::distance(std::upper_bound(msb.rbegin(), msb.rend(), m),
                                  msb.rend());
    v.emplace(std::next(v.begin(), idx), val);
    msb.emplace(std::next(msb.begin(), idx), m);
    for (int i = idx + 1; i <= n; ++i) {
      if (v[idx][msb[i]]) v[idx] ^= v[i];
    }
    for (int i = idx - 1; i >= 0; --i) {
      if (v[i][m]) v[i] ^= v[idx];
    }
    return true;
  }

  int rank() const { return v.size(); }

  inline bool operator<(const Basis& x) const {
    const int n = v.size();
    if (n != x.rank()) return n < x.rank();
    if (n == D) return false;
    for (int i = 0; i < n; ++i) {
      if (msb[i] != x.msb[i]) return msb[i] < x.msb[i];
    }
    for (int i = 0; i < n; ++i) {
      for (int j = msb[i] - 1; ; --j) {
        if (v[i][j] != x.v[i][j]) return x.v[i][j];
      }
    }
    return false;
  }
};

}  // namespace emthrm

#endif  // EMTHRM_MATH_BASIS_HPP_
#line 1 "include/emthrm/math/basis.hpp"



#include <algorithm>
#include <bitset>
#include <iterator>
#include <vector>

namespace emthrm {

template <int D>
struct Basis {
  std::vector<std::bitset<D>> v;
  std::vector<int> msb;

  Basis() = default;

  bool add(std::bitset<D> val) {
    const int n = rank();
    if (n == D) return false;
    for (int i = 0; i < n; ++i) {
      if (val[msb[i]]) val ^= v[i];
    }
    if (val.none()) return false;
    int m = D - 1;
    while (!val[m]) --m;
    if (v.empty()) [[unlikely]] {
      v.emplace_back(val);
      msb.emplace_back(m);
      return true;
    }
    const int idx = std::distance(std::upper_bound(msb.rbegin(), msb.rend(), m),
                                  msb.rend());
    v.emplace(std::next(v.begin(), idx), val);
    msb.emplace(std::next(msb.begin(), idx), m);
    for (int i = idx + 1; i <= n; ++i) {
      if (v[idx][msb[i]]) v[idx] ^= v[i];
    }
    for (int i = idx - 1; i >= 0; --i) {
      if (v[i][m]) v[i] ^= v[idx];
    }
    return true;
  }

  int rank() const { return v.size(); }

  inline bool operator<(const Basis& x) const {
    const int n = v.size();
    if (n != x.rank()) return n < x.rank();
    if (n == D) return false;
    for (int i = 0; i < n; ++i) {
      if (msb[i] != x.msb[i]) return msb[i] < x.msb[i];
    }
    for (int i = 0; i < n; ++i) {
      for (int j = msb[i] - 1; ; --j) {
        if (v[i][j] != x.v[i][j]) return x.v[i][j];
      }
    }
    return false;
  }
};

}  // namespace emthrm
Back to top page