提出 #76708233
ソースコード 拡げる
#include <cstddef>
#include <cstdint>
namespace stew
{
namespace integer_type
{
using u8 = std::uint8_t;
using u16 = std::uint16_t;
using u32 = std::uint32_t;
using u64 = std::uint64_t;
using i8 = std::int8_t;
using i16 = std::int16_t;
using i32 = std::int32_t;
using i64 = std::int64_t;
using i128 = __int128;
using usize = std::size_t;
}
using namespace integer_type;
}
#include <concepts>
namespace stew
{
template<class T>
struct IOCustom;
template<class T>
concept io_custom = requires(const T imut)
{
{IOCustom<T>::to_output(imut)} -> std::same_as<void>;
{IOCustom<T>::from_input()} -> std::convertible_to<T>;
};
}
#include <concepts>
#include <ranges>
#include <iterator>
#include <iostream>
#include <print>
namespace stew
{
inline std::istream * in_p = &std::cin;
// template<class T>
// struct FromInput;
struct InStreamPin final
{
std::istream * last;
InStreamPin(std::istream& in) noexcept:
last{in_p}
{
in_p = ∈
}
~InStreamPin()
{
in_p = last;
}
};
struct IPipeTrait
{};
template<class T>
concept input_pipe = requires(typename T::Element e)
{
requires std::derived_from<T, IPipeTrait>;
{T::pipe(e)} -> std::same_as<void>;
};
template<class T>
inline consteval auto is_normal_inputable() -> bool
{
return requires{*in_p >> std::declval<T&>();};
}
// template<class T>
// inline consteval auto is_from_input_inputable() -> bool
// {
// return requires{FromInput<T>::from_input();};
// }
template<class T>
inline consteval auto is_custom_inputable() -> bool
{
return requires{IOCustom<T>::from_input();};
}
// 再帰的なので、コンセプト直では無理。関数をかませないといけない
template<class T>
inline consteval auto is_inputable() -> bool;
template<class T>
inline consteval auto is_input_pipe_inputable() -> bool
{
if constexpr(input_pipe<T>)
{
return is_inputable<typename T::Element>();
}
else return false;
}
template<class T>
inline consteval auto is_range_inputable() -> bool;
template<class T>
inline consteval auto is_inputable() -> bool
{
return is_normal_inputable<T>() ||
is_input_pipe_inputable<T>() ||
// is_from_input_inputable<T>() ||
is_custom_inputable<T>() ||
is_range_inputable<T>();
}
template<class T>
inline consteval auto is_range_inputable() -> bool
{
if constexpr(std::ranges::range<T>)
{
return is_inputable<std::ranges::range_value_t<T>>();
}
else return false;
}
template<class T>
concept inputable = is_inputable<T>();
template<inputable T>
inline auto input();
namespace impl
{
template<class T>
using ReturnInputE = decltype(input<T>());
}
template<inputable T>
inline auto input()
{
// if constexpr(is_from_input_inputable<T>())
// {
// return FromInput<T>::from_input();
// }
if constexpr(is_input_pipe_inputable<T>())
{
auto value = input<typename T::Element>();
T::pipe(value);
return value;
}
else if constexpr(is_custom_inputable<T>())
{
return IOCustom<T>::from_input();
}
else if constexpr(is_normal_inputable<T>())
{
T value{};
*in_p >> value;
return value;
}
else
{
static_assert([]{return false;}(), "WTF!!?");
}
}
template<class ... Args>
inline auto inputs() -> std::tuple<impl::ReturnInputE<Args>...>
{
return {input<Args>()...};
}
// アロケート済み範囲に入力する
// 型によるアロケート済みでない部分までのガードが必要
// ex) std::vector<std::vector<NotAllocated<std::tuple<std::vector<int>, int, bool>>>>
// ガードをネストできない(実行時にサイズが決まる場合など)ため、やり方を変えるべきか。
// std::vector</* ... */> vec;
// input_into(vec, SizeTag<"a">(a), SizeTag<"b">(b), SizeTag<"c">(c));
// みたいな。
//
// template<inputable T>
// inline void input_into_piped_range(impl::ReturnInputE<T>& into_value)
// {
// if constexpr(is_input_pipe_inputable<T>())
// {
// auto value = input<typename T::Element>();
// T::pipe(value);
// into_value = std::move(value);
// }
// else if constexpr(is_custom_inputable<T>())
// {
// into_value = IOCustom<T>::from_input();
// }
// else if constexpr(is_normal_inputable<T>())
// {
// T value{};
// *in_p >> value;
// into_value = std::move(value);
// }
// else if constexpr(is_range_inputable<T>())
// {
// using E = std::ranges::range_value_t<T>;
// for(auto& e : into_value) e = input<E>();
// }
// else
// {
// static_assert([]{return false;}(), "WTF!!?");
// }
// }
// template<inputable T>
// inline void input_into_range(T& into_value)
// {
// input_into_piped_range<T>(into_value);
// }
}
#include <vector>
#include <span>
#include <ranges>
#include <utility>
#include <algorithm>
namespace stew::sparse_matrix {
template<class E_ = void>
struct Csr final {
std::vector<E_> data;
std::vector<usize> acc_row;
std::vector<usize> col;
auto row(const usize index) {
auto f = [this](const usize i) -> std::pair<usize, E_&> {
return {this->col[i], this->data[i]};
};
if(index >= this->acc_row.size() - 1) {
return std::views::iota(usize(0), usize(0))
| std::views::transform(std::move(f));
}
else {
return std::views::iota(this->acc_row[index], this->acc_row[index + 1])
| std::views::transform(std::move(f));
}
}
auto c_row(const usize index) const {
auto f = [this](const usize i) -> std::pair<usize, const E_&> {
return {this->col[i], this->data[i]};
};
if(index >= this->acc_row.size() - 1) {
return std::views::iota(usize(0), usize(0))
| std::views::transform(std::move(f));
}
else {
return std::views::iota(this->acc_row[index], this->acc_row[index + 1])
| std::views::transform(std::move(f));
}
}
auto view() {
return std::views::iota(0u, this->acc_row.size() - 1)
| std::views::transform([this](const usize i) {
return this->row(i);
});
}
auto c_view() const {
return std::views::iota(0u, this->acc_row.size() - 1)
| std::views::transform([this](const usize i) {
return this->c_row(i);
});
}
auto begin() {
return this->view().begin();
}
auto end() {
return this->view().end();
}
auto cbegin() const {
return this->c_view().begin();
}
auto cend() const {
return this->c_view().end();
}
};
template<>
struct Csr<> final {
std::vector<usize> acc_row;
std::vector<usize> col;
auto row(const usize index) {
auto f = [this](const usize i) -> usize {
return this->col[i];
};
if(index >= this->acc_row.size() - 1) {
return std::views::iota(usize(0), usize(0))
| std::views::transform(std::move(f));
}
else {
return std::views::iota(this->acc_row[index], this->acc_row[index + 1])
| std::views::transform(std::move(f));
}
}
auto c_row(const usize index) const {
auto f = [this](const usize i) -> usize {
return this->col[i];
};
if(index >= this->acc_row.size() - 1) {
return std::views::iota(usize(0), usize(0))
| std::views::transform(std::move(f));
}
else {
return std::views::iota(this->acc_row[index], this->acc_row[index + 1])
| std::views::transform(std::move(f));
}
}
auto view() {
return std::views::iota(0u, this->acc_row.size() - 1)
| std::views::transform([this](const usize i) {
return this->row(i);
});
}
auto c_view() const {
return std::views::iota(0u, this->acc_row.size() - 1)
| std::views::transform([this](const usize i) {
return this->c_row(i);
});
}
auto begin() {
return this->view().begin();
}
auto end() {
return this->view().end();
}
auto cbegin() const {
return this->c_view().begin();
}
auto cend() const {
return this->c_view().end();
}
};
template<class E_ = void>
struct Coo final {
std::vector<std::pair<std::pair<usize, usize>, E_>> buffer;
bool is_sorted = false;
static auto make(const usize buffer_size) {
auto buffer = std::vector<std::pair<std::pair<usize, usize>, E_>>{};
buffer.reserve(buffer_size);
return Coo<E_> {
.buffer = std::move(buffer),
.is_sorted = false
};
}
void add(const std::pair<usize, usize>& index, E_&& elem) {
this->is_sorted = false;
this->buffer.emplace_back(std::pair<std::pair<usize, usize>, E_>{index, std::move(elem)});
}
void sort() {
std::ranges::sort(this->buffer);
this->is_sorted = true;
}
auto to_csr(const usize row_size) && -> Csr<E_>
// [[expect: indices are sorted by row and then by column]]
{
if(not this->is_sorted) {
this->sort();
}
std::vector<E_> data{};
std::vector<usize> acc_row{};
std::vector<usize> col{};
data.reserve(this->buffer.size());
acc_row.reserve(row_size + 1);
col.reserve(this->buffer.size());
for(const auto& [index, elem] : this->buffer) {
data.emplace_back(std::move(elem));
col.emplace_back(index.second);
}
auto it = this->buffer.begin();
for(usize i = 0; i < row_size; ++i) {
acc_row.push_back(it - this->buffer.begin());
while(it != this->buffer.end() && it->first.first == i) {
++it;
}
}
acc_row.push_back(this->buffer.size());
return Csr<E_> {
.data = std::move(data),
.acc_row = std::move(acc_row),
.col = std::move(col)
};
}
};
template<>
struct Coo<> final {
std::vector<std::pair<usize, usize>> buffer;
bool is_sorted = false;
static auto make(const usize buffer_size) {
auto buffer = std::vector<std::pair<usize, usize>>{};
buffer.reserve(buffer_size);
return Coo<> {
.buffer = std::move(buffer),
.is_sorted = false
};
}
void add(const std::pair<usize, usize>& index) {
this->is_sorted = false;
this->buffer.push_back(index);
}
void sort() {
std::ranges::sort(this->buffer);
this->is_sorted = true;
}
auto to_csr(const usize row_size) && -> Csr<> {
if(not this->is_sorted) {
this->sort();
}
std::vector<usize> acc_row{};
std::vector<usize> col{};
acc_row.reserve(row_size + 1);
col.reserve(this->buffer.size());
for(const auto& index : this->buffer) {
col.push_back(index.second);
}
auto it = this->buffer.begin();
for(usize i = 0; i < row_size; ++i) {
acc_row.push_back(it - this->buffer.begin());
while(it != this->buffer.end() && it->first == i) {
++it;
}
}
acc_row.push_back(this->buffer.size());
return Csr<> {
.acc_row = std::move(acc_row),
.col = std::move(col)
};
}
};
}
#include <cstddef>
#include <utility>
#include <vector>
#include <optional>
namespace stew {
template<class T_ = void>
struct UnionFind final {
std::vector<usize> root;
std::vector<usize> size;
std::vector<T_> data;
constexpr UnionFind(std::vector<T_>&& data) noexcept
: root(data.size())
, size(data.size(), 1)
, data(std::move(data))
{
for(usize i = 0; i < this->data.size(); ++i) {
this->root[i] = i;
}
}
constexpr auto get(const usize x) const noexcept -> const T_& {
return this->data[this->find(x)];
}
constexpr auto get(const usize x) noexcept -> T_& {
return this->data[this->find(x)];
}
constexpr auto find(const usize x) noexcept -> usize {
if(this->root[x] == x) {
return x;
} else {
return this->root[x] = this->find(this->root[x]);
}
}
constexpr auto unite(usize x, usize y, auto&& f, bool call_when_same) noexcept -> std::optional<usize>
requires requires(T_ vx, T_ vy, bool is_x) {
{f(vx, vy, is_x)} -> std::same_as<T_>;
} {
x = this->find(x);
y = this->find(y);
if(x == y) {
if(call_when_same) {
this->data[x] = f(this->data[x], this->data[y], true);
}
return std::nullopt;
}
bool is_x = true;
if(this->size[x] < this->size[y]) {
std::swap(x, y);
is_x = false;
}
this->root[y] = x;
this->size[x] += this->size[y];
this->data[x] = f(this->data[x], this->data[y], is_x);
return x;
}
};
template<>
struct UnionFind<void> final {
std::vector<usize> root;
std::vector<usize> size;
constexpr UnionFind(const usize n) noexcept
: root(n)
, size(n, 1)
{
for(usize i = 0; i < n; ++i) {
this->root[i] = i;
}
}
constexpr auto find(const usize x) noexcept -> usize {
if(this->root[x] == x) {
return x;
} else {
return this->root[x] = this->find(this->root[x]);
}
}
constexpr auto unite(usize x, usize y) noexcept -> std::optional<usize> {
x = this->find(x);
y = this->find(y);
if(x == y) {
return std::nullopt;
}
if(this->size[x] < this->size[y]) std::swap(x, y);
this->root[y] = x;
this->size[x] += this->size[y];
return x;
}
};
}
namespace stew::i_pipes
{
template<class T>
requires std::integral<T>
struct Decrementer final : IPipeTrait
{
using Element = T;
static auto pipe(T& mut) -> void
{
--mut;
}
};
}
namespace stew {
template<class T>
using D = i_pipes::Decrementer<T>;
}
#include <unordered_set>
#include <set>
#include <unordered_map>
#include <list>
#include <map>
#include <queue>
#include <concepts>
#include <utility>
namespace stew::binary_search {
template<class T_, class MiddleF_ = decltype([]<class Int_> requires std::integral<Int_> (const Int_& l, const Int_& r){return (l + r) / 2;})>
inline auto binary_search(const T_& left, const T_& right, const auto& pred, const bool left_is, const MiddleF_& middle = {}) -> std::pair<T_, T_> requires
requires(const T_ v) {
{pred(v)} -> std::convertible_to<bool>;
{middle(left, right)} -> std::convertible_to<T_>;
}
{
T_ l = left;
T_ r = right;
while(r - l > 1) {
const T_ mid = middle(l, r);
if(pred(mid) ^ left_is) {
r = mid;
} else {
l = mid;
}
}
return {l, r};
}
}
#include <concepts>
#include <type_traits>
namespace stew {
template<class T_, class U_>
concept univ_ref = std::same_as<std::remove_cvref_t<T_>, U_>;
}
#include <concepts>
namespace stew::monoid
{
template<class T_>
struct Monoid {
static_assert([]{return false;}(), "No Monoid defined for this type");
};
template<class T_>
concept monoid = requires(const T_ imut1, const T_ imut2)
{
{Monoid<T_>::op(imut1, imut2)} -> std::same_as<T_>;
{Monoid<T_>::ide()} -> std::same_as<T_>;
};
}
#include <cstddef>
#include <stdexcept>
#include <vector>
namespace stew::swag::impl {
using monoid::Monoid;
template<monoid::monoid T_>
struct Swag final {
using M = Monoid<T_>;
std::vector<std::pair<T_, T_>> back{{M::ide(), M::ide()}};
std::vector<std::pair<T_, T_>> front{{M::ide(), M::ide()}};
std::vector<T_> buf{};
constexpr void push_back(univ_ref<T_> auto&& x_) {
T_ x{std::forward<decltype(x_)>(x_)};
const auto& [_, acc_] = this->back.back();
T_ acc = M::op(acc_, x);
this->back.emplace_back(std::move(x), std::move(acc));
}
constexpr void push_front(univ_ref<T_> auto&& x_) {
T_ x{std::forward<decltype(x_)>(x_)};
const auto& [_, acc_] = this->front.back();
T_ acc = M::op(x, acc_);
this->front.emplace_back(std::move(x), std::move(acc));
}
constexpr auto pop_back() noexcept -> T_ {
if(this->back.size() == 1 && this->front.size() == 1) {
throw std::runtime_error{"panic! pop_back from empty swag."};
}
if(this->back.size() == 1) {
const usize k = this->front.size() - 1;
const usize moved = (k - 1) / 2;
const usize stay = k - 1 - moved;
// 先頭~約半分をbufに退避
this->buf.clear();
for(usize i = 0; i < stay; ++i) {
auto x = std::move(this->front.back().first);
this->buf.emplace_back(std::move(x));
this->front.pop_back();
}
// 約半分~末尾-1をbackに追加
for(usize i = 0; i < moved; ++i) {
auto x = std::move(this->front.back().first);
this->push_back(std::move(x));
this->front.pop_back();
}
// 末尾をpop
auto ret = std::move(this->front.back().first);
this->front.pop_back();
// bufの退避を戻す
for(usize i = 0; i < stay; ++i) {
this->push_front(std::move(this->buf.back()));
this->buf.pop_back();
}
this->buf.clear();
return ret;
}
else {
auto ret = std::move(this->back.back().first);
this->back.pop_back();
return ret;
}
}
constexpr auto pop_front() noexcept -> T_ {
if(this->back.size() == 1 && this->front.size() == 1) {
throw std::runtime_error{"panic! pop_front from empty swag."};
}
if(this->front.size() == 1) {
const usize k = this->back.size() - 1;
const usize moved = (k - 1) / 2;
const usize stay = k - 1 - moved;
// 末尾~約半分をbufに退避
this->buf.clear();
for(usize i = 0; i < stay; ++i) {
auto x = std::move(this->back.back().first);
this->buf.emplace_back(std::move(x));
this->back.pop_back();
}
// 約半分~先頭-1をfrontに追加
for(usize i = 0; i < moved; ++i) {
auto x = std::move(this->back.back().first);
this->push_front(std::move(x));
this->back.pop_back();
}
// 先頭をpop
auto ret = std::move(this->back.back().first);
this->back.pop_back();
// bufの退避を戻す
for(usize i = 0; i < stay; ++i) {
this->push_back(std::move(this->buf.back()));
this->buf.pop_back();
}
this->buf.clear();
return ret;
}
else {
auto ret = std::move(this->front.back().first);
this->front.pop_back();
return ret;
}
}
constexpr auto fold() const noexcept -> T_ {
return M::op(this->front.back().second, this->back.back().second);
}
};
}
#include <algorithm>
#include <concepts>
#include <type_traits>
#include <utility>
#include <vector>
namespace stew::shakutori {
// 内部可変性で外側にはimutableなものに`mutable`を使うのがちょっと不安なので、
// 本来constであるべきものをconstにせず制約づけてる
// 内部可変性のメンタルモデルがあんまりない...
// noexceptも同様に無視してる
// ビバ償却定数!
template<class T_>
concept slide_window = requires(T_& mut) {
typename T_::Element;
typename T_::Ret;
requires requires (const T_::Element& e) {
{mut.extend_r(e)};
{mut.shrink_l(e)};
{mut.value()} -> std::convertible_to<typename T_::Ret>;
};
};
template<class T_>
concept tryable_slide_window = slide_window<T_> && requires(const T_::Element& e, T_& mut) {
{mut.shrink_r(e)};
};
// ほんとはstd::generatorで書くべきかも
template<class Ret_, bool is_true_continue, class Idx_>
inline constexpr auto shak_window(auto& prop, auto& range_to_val, auto& arr, const std::pair<Idx_, Idx_>& haop) noexcept -> std::vector<Ret_>
requires
(tryable_slide_window<std::remove_cvref_t<decltype(prop)>> && std::convertible_to<typename std::remove_cvref_t<decltype(prop)>::Ret, bool>)
&& (slide_window<std::remove_cvref_t<decltype(range_to_val)>> && std::convertible_to<typename std::remove_cvref_t<decltype(range_to_val)>::Ret, Ret_>)
&& (std::same_as<std::remove_cvref_t<decltype(arr(std::declval<Idx_>()))>, typename std::remove_cvref_t<decltype(prop)>::Element> && std::same_as<typename std::remove_cvref_t<decltype(prop)>::Element, typename std::remove_cvref_t<decltype(range_to_val)>::Element>)
{
const auto& [bi, en] = haop;
std::vector<Ret_> ret{};
Idx_ r = bi;
for(Idx_ l = bi; l < en; ++l) {
r = std::max<Idx_>(l, r);
while(r < en) {
prop.extend_r(arr(r));
const bool prop_val = prop.value();
if(prop_val == is_true_continue) {
range_to_val.extend_r(arr(r));
++r;
}
else {
prop.shrink_r(arr(r));
break;
}
}
ret.emplace_back(range_to_val.value());
if(l != r) {
prop.shrink_l(arr(l));
range_to_val.shrink_l(arr(l));
}
}
return ret;
}
// std::generatorで書きたいかも
template<bool is_true_continue, class Idx_>
inline constexpr auto shak(auto& prop, const std::pair<Idx_, Idx_>& haop) noexcept -> std::vector<std::pair<Idx_, Idx_>>
requires requires(const Idx_& l, const Idx_& r) {
{prop(l, r)} -> std::convertible_to<bool>;
} {
const auto& [bi, en] = haop;
std::vector<std::pair<Idx_, Idx_>> ret{};
Idx_ r = bi;
for(Idx_ l = bi; l < en; ++l) {
r = std::max<Idx_>(l, r);
while(r < en) {
const bool prop_val = prop(l, r + 1);
if(prop_val == is_true_continue) {
++r;
}
else {
break;
}
}
ret.emplace_back(l, r);
}
return ret;
}
}
using namespace stew;
int main() {
std::array<std::array<i64, 6>, 3> dices{};
for(i64 id = 0; id < 3; ++id) {
for(i64 im = 0; im < 6; ++im) {
dices[id][im] = input<i64>();
}
}
i64 ans = 0;
for(i64 i1 = 0; i1 < 6; ++i1) {
for(i64 i2 = 0; i2 < 6; ++i2) {
for(i64 i3 = 0; i3 < 6; ++i3) {
if(std::set{dices[0][i1], dices[1][i2], dices[2][i3]} == std::set<i64>{4, 5, 6}) {
++ans;
}
}
}
}
std::println("{:.20}", (long double)(ans) / 216);
}
提出情報
| 提出日時 |
|
| 問題 |
D - 456 |
| ユーザ |
Klow |
| 言語 |
C++23 (GCC 15.2.0) |
| 得点 |
200 |
| コード長 |
21868 Byte |
| 結果 |
AC |
| 実行時間 |
13 ms |
| メモリ |
6764 KiB |
ジャッジ結果
| セット名 |
Sample |
All |
| 得点 / 配点 |
0 / 0 |
200 / 200 |
| 結果 |
|
|
| セット名 |
テストケース |
| Sample |
sample_01.txt, sample_02.txt |
| All |
random_01.txt, random_02.txt, random_03.txt, random_04.txt, random_05.txt, random_06.txt, random_07.txt, random_08.txt, random_09.txt, random_10.txt, random_11.txt, random_12.txt, sample_01.txt, sample_02.txt |
| ケース名 |
結果 |
実行時間 |
メモリ |
| random_01.txt |
AC |
13 ms |
6564 KiB |
| random_02.txt |
AC |
2 ms |
6716 KiB |
| random_03.txt |
AC |
2 ms |
6552 KiB |
| random_04.txt |
AC |
2 ms |
6764 KiB |
| random_05.txt |
AC |
2 ms |
6552 KiB |
| random_06.txt |
AC |
2 ms |
6712 KiB |
| random_07.txt |
AC |
2 ms |
6704 KiB |
| random_08.txt |
AC |
2 ms |
6712 KiB |
| random_09.txt |
AC |
2 ms |
6660 KiB |
| random_10.txt |
AC |
2 ms |
6712 KiB |
| random_11.txt |
AC |
2 ms |
6552 KiB |
| random_12.txt |
AC |
2 ms |
6456 KiB |
| sample_01.txt |
AC |
2 ms |
6736 KiB |
| sample_02.txt |
AC |
2 ms |
6660 KiB |