This documentation is automatically generated by online-judge-tools/verification-helper
#define PROBLEM "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=ITP1_1_A"
#include <algorithm>
#include <cassert>
#include <chrono>
#include <iostream>
#include <vector>
#include "library/util/subset_iterator.hpp"
void test_all_subset_k(uint32_t s, uint32_t k) {
std::vector<uint32_t> expected;
if (__builtin_popcount(s) >= k) {
for (uint32_t i = 0; i <= s; ++i) if ((i & s) == i and __builtin_popcount(i) == k) {
expected.push_back(i);
}
}
std::vector<uint32_t> actual;
for (uint32_t t : suisen::all_subset_k(s, k)) {
actual.push_back(t);
}
std::sort(expected.begin(), expected.end());
std::sort(actual.begin(), actual.end());
assert(expected == actual);
}
void run_test() {
for (uint32_t s = 0; s < 10000; ++s) for (uint32_t k = 0; k <= 15; ++k) {
test_all_subset_k(s, k);
}
}
void perf_test() {
const uint32_t s = 0b0111'1111'1111'1111'1111'1111'1111'1111;
const uint32_t k = 15;
std::cerr << "|S| = " << __builtin_popcount(s) << ", k = " << k << std::endl;
auto start = std::chrono::system_clock::now();
uint64_t cnt = 0;
for (uint32_t t : suisen::all_subset_k(s, k)) ++cnt;
auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now() - start).count();
std::cerr << "Elapsed Time : " << elapsed << " ms" << std::endl;
std::cerr << "Number of subsets of S with k elements : " << cnt << std::endl;
}
int main() {
run_test();
perf_test();
std::cout << "Hello World" << std::endl;
return 0;
}#line 1 "test/src/util/subset_iterator/dummy_all_subset_k.test.cpp"
#define PROBLEM "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=ITP1_1_A"
#include <algorithm>
#include <cassert>
#include <chrono>
#include <iostream>
#include <vector>
#line 1 "library/util/subset_iterator.hpp"
#ifdef _MSC_VER
# include <intrin.h>
#else
# include <x86intrin.h>
#endif
#line 11 "library/util/subset_iterator.hpp"
#include <cstdint>
#line 13 "library/util/subset_iterator.hpp"
#include <limits>
namespace suisen {
template <typename T, std::enable_if_t<std::is_integral_v<T>, std::nullptr_t> = nullptr>
struct all_subset {
struct all_subset_iter {
const T s; T t;
constexpr all_subset_iter(T s) : s(s), t(s + 1) {}
constexpr auto operator*() const { return t; }
constexpr auto operator++() {}
constexpr auto operator!=(std::nullptr_t) { return t ? (--t &= s, true) : false; }
};
T s;
constexpr all_subset(T s) : s(s) {}
constexpr auto begin() { return all_subset_iter(s); }
constexpr auto end() { return nullptr; }
};
// iterator over T s.t. T is subset of S and |T| = k
struct all_subset_k {
struct all_subset_k_iter {
const uint32_t n, k, s;
uint32_t t;
__attribute__((target("avx2")))
all_subset_k_iter(uint32_t s, uint32_t k) : n(uint32_t(1) << _mm_popcnt_u32(s)), k(k), s(s), t((uint32_t(1) << k) - 1) {}
__attribute__((target("bmi2")))
auto operator*() const { return _pdep_u32(t, s); }
__attribute__((target("bmi")))
auto operator++() {
if (k == 0) {
t = std::numeric_limits<uint32_t>::max();
} else {
uint32_t y = t + _blsi_u32(t); // t + (-t & t)
t = y | ((y ^ t) >> _tzcnt_u32(t << 2));
}
}
auto operator!=(std::nullptr_t) const { return t < n; }
};
uint32_t s, k;
all_subset_k(uint32_t s, uint32_t k) : s(s), k(k) {
assert(s != std::numeric_limits<uint32_t>::max());
}
static all_subset_k nCk(uint32_t n, uint32_t k) { return all_subset_k((uint32_t(1) << n) - 1, k); }
auto begin() { return all_subset_k_iter(s, k); }
auto end() { return nullptr; }
};
struct all_subset_k_64 {
struct all_subset_k_iter_64 {
const uint64_t n, s;
const uint32_t k;
uint64_t t;
__attribute__((target("avx2")))
all_subset_k_iter_64(uint64_t s, uint32_t k) : n(uint64_t(1) << _mm_popcnt_u64(s)), s(s), k(k), t((uint64_t(1) << k) - 1) {}
__attribute__((target("bmi2")))
auto operator*() const { return _pdep_u64(t, s); }
__attribute__((target("bmi")))
auto operator++() {
if (k == 0) {
t = std::numeric_limits<uint64_t>::max();
} else {
uint64_t y = t + _blsi_u64(t);
t = y | ((y ^ t) >> _tzcnt_u64(t << 2));
}
}
auto operator!=(std::nullptr_t) const { return t < n; }
};
uint64_t s;
uint32_t k;
all_subset_k_64(uint64_t s, uint32_t k) : s(s), k(k) {
assert(s != std::numeric_limits<uint64_t>::max());
}
auto begin() { return all_subset_k_iter_64(s, k); }
auto end() { return nullptr; }
};
struct all_setbit {
struct all_setbit_iter {
uint32_t s;
all_setbit_iter(uint32_t s) : s(s) {}
__attribute__((target("bmi")))
auto operator*() { return _tzcnt_u32(s); }
__attribute__((target("bmi")))
auto operator++() { s = __blsr_u32(s); }
auto operator!=(std::nullptr_t) { return s; }
};
uint32_t s;
all_setbit(uint32_t s) : s(s) {}
auto begin() { return all_setbit_iter(s); }
auto end() { return nullptr; }
};
struct all_setbit_64 {
struct all_setbit_iter_64 {
uint64_t s;
all_setbit_iter_64(uint64_t s) : s(s) {}
__attribute__((target("bmi")))
auto operator*() { return _tzcnt_u64(s); }
__attribute__((target("bmi")))
auto operator++() { s = __blsr_u64(s); }
auto operator!=(std::nullptr_t) { return s; }
};
uint64_t s;
all_setbit_64(uint64_t s) : s(s) {}
auto begin() { return all_setbit_iter_64(s); }
auto end() { return nullptr; }
};
} // namespace suisen
#line 10 "test/src/util/subset_iterator/dummy_all_subset_k.test.cpp"
void test_all_subset_k(uint32_t s, uint32_t k) {
std::vector<uint32_t> expected;
if (__builtin_popcount(s) >= k) {
for (uint32_t i = 0; i <= s; ++i) if ((i & s) == i and __builtin_popcount(i) == k) {
expected.push_back(i);
}
}
std::vector<uint32_t> actual;
for (uint32_t t : suisen::all_subset_k(s, k)) {
actual.push_back(t);
}
std::sort(expected.begin(), expected.end());
std::sort(actual.begin(), actual.end());
assert(expected == actual);
}
void run_test() {
for (uint32_t s = 0; s < 10000; ++s) for (uint32_t k = 0; k <= 15; ++k) {
test_all_subset_k(s, k);
}
}
void perf_test() {
const uint32_t s = 0b0111'1111'1111'1111'1111'1111'1111'1111;
const uint32_t k = 15;
std::cerr << "|S| = " << __builtin_popcount(s) << ", k = " << k << std::endl;
auto start = std::chrono::system_clock::now();
uint64_t cnt = 0;
for (uint32_t t : suisen::all_subset_k(s, k)) ++cnt;
auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now() - start).count();
std::cerr << "Elapsed Time : " << elapsed << " ms" << std::endl;
std::cerr << "Number of subsets of S with k elements : " << cnt << std::endl;
}
int main() {
run_test();
perf_test();
std::cout << "Hello World" << std::endl;
return 0;
}