From 3c14bbd524ddedbddf495157de314d289563c23c Mon Sep 17 00:00:00 2001 From: noshi91 Date: Wed, 6 May 2020 23:32:15 +0900 Subject: [PATCH 1/2] add enumerate_triangles --- graph/enumerate_triangles/checker.cpp | 62 +++++++++++++++++++ graph/enumerate_triangles/gen/erdos_renyi.h | 53 ++++++++++++++++ graph/enumerate_triangles/gen/example_00.in | 7 +++ .../enumerate_triangles/gen/large_random.cpp | 15 +++++ graph/enumerate_triangles/gen/max_random.cpp | 13 ++++ graph/enumerate_triangles/gen/minimum_00.in | 3 + graph/enumerate_triangles/gen/small_dense.cpp | 18 ++++++ .../enumerate_triangles/gen/small_sparse.cpp | 20 ++++++ graph/enumerate_triangles/hash.json | 30 +++++++++ graph/enumerate_triangles/info.toml | 36 +++++++++++ graph/enumerate_triangles/sol/correct.cpp | 61 ++++++++++++++++++ .../enumerate_triangles/sol/correct_slow.cpp | 58 +++++++++++++++++ graph/enumerate_triangles/sol/naive.cpp | 37 +++++++++++ graph/enumerate_triangles/task.md | 60 ++++++++++++++++++ graph/enumerate_triangles/verifier.cpp | 34 ++++++++++ 15 files changed, 507 insertions(+) create mode 100644 graph/enumerate_triangles/checker.cpp create mode 100644 graph/enumerate_triangles/gen/erdos_renyi.h create mode 100644 graph/enumerate_triangles/gen/example_00.in create mode 100644 graph/enumerate_triangles/gen/large_random.cpp create mode 100644 graph/enumerate_triangles/gen/max_random.cpp create mode 100644 graph/enumerate_triangles/gen/minimum_00.in create mode 100644 graph/enumerate_triangles/gen/small_dense.cpp create mode 100644 graph/enumerate_triangles/gen/small_sparse.cpp create mode 100644 graph/enumerate_triangles/hash.json create mode 100644 graph/enumerate_triangles/info.toml create mode 100644 graph/enumerate_triangles/sol/correct.cpp create mode 100644 graph/enumerate_triangles/sol/correct_slow.cpp create mode 100644 graph/enumerate_triangles/sol/naive.cpp create mode 100644 graph/enumerate_triangles/task.md create mode 100644 graph/enumerate_triangles/verifier.cpp diff --git a/graph/enumerate_triangles/checker.cpp b/graph/enumerate_triangles/checker.cpp new file mode 100644 index 000000000..6a66d5330 --- /dev/null +++ b/graph/enumerate_triangles/checker.cpp @@ -0,0 +1,62 @@ +// https://github.com/MikeMirzayanov/testlib/blob/master/checkers/wcmp.cpp + +// The MIT License (MIT) + +// Copyright (c) 2015 Mike Mirzayanov + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +#include "testlib.h" + +using namespace std; + +int main(int argc, char * argv[]) +{ + setName("compare sequences of tokens"); + registerTestlibCmd(argc, argv); + + int n = 0; + string j, p; + + while (!ans.seekEof() && !ouf.seekEof()) + { + n++; + + ans.readWordTo(j); + ouf.readWordTo(p); + + if (j != p) + quitf(_wa, "%d%s words differ - expected: '%s', found: '%s'", n, englishEnding(n).c_str(), compress(j).c_str(), compress(p).c_str()); + } + + if (ans.seekEof() && ouf.seekEof()) + { + if (n == 1) + quitf(_ok, "\"%s\"", compress(j).c_str()); + else + quitf(_ok, "%d tokens", n); + } + else + { + if (ans.seekEof()) + quitf(_wa, "Participant output contains extra tokens"); + else + quitf(_wa, "Unexpected EOF in the participants output"); + } +} diff --git a/graph/enumerate_triangles/gen/erdos_renyi.h b/graph/enumerate_triangles/gen/erdos_renyi.h new file mode 100644 index 000000000..94f0a0549 --- /dev/null +++ b/graph/enumerate_triangles/gen/erdos_renyi.h @@ -0,0 +1,53 @@ +#include "random.h" +#include +#include +#include +#include +#include + +void erdos_renyi(int n, int m, Random &gen) { + assert(static_cast(n) * (n - 1) / 2 >= m); + + std::vector xs(n); + for (auto &x : xs) { + x = gen.uniform(0, MOD - 1); + } + + std::vector> edges(m); + if (static_cast(n) * (n - 1) / 2 > m * 2) { + // sparse + std::set> eset; + for (auto &e : edges) { + do { + e = gen.uniform_pair(0, n - 1); + } while (!eset.insert(std::minmax(e.first, e.second)).second); + } + } else { + // dense + std::vector> all; + for (int u = 0; u < n; ++u) { + for (int v = 0; v < u; ++v) { + if (gen.uniform_bool()) { + all.emplace_back(u, v); + } else { + all.emplace_back(v, u); + } + } + } + gen.shuffle(all.begin(), all.end()); + std::copy(all.begin(), all.begin() + m, edges.begin()); + } + + std::printf("%d %d\n", n, m); + for (int i = 0; i < n; ++i) { + std::printf("%d", xs[i]); + if (i != n - 1) { + std::printf(" "); + } else { + std::printf("\n"); + } + } + for (const auto &e : edges) { + std::printf("%d %d\n", e.first, e.second); + } +} diff --git a/graph/enumerate_triangles/gen/example_00.in b/graph/enumerate_triangles/gen/example_00.in new file mode 100644 index 000000000..83a336bfa --- /dev/null +++ b/graph/enumerate_triangles/gen/example_00.in @@ -0,0 +1,7 @@ +4 5 +1 2 3 4 +0 3 +2 0 +2 1 +2 3 +1 3 diff --git a/graph/enumerate_triangles/gen/large_random.cpp b/graph/enumerate_triangles/gen/large_random.cpp new file mode 100644 index 000000000..b4d9f77dd --- /dev/null +++ b/graph/enumerate_triangles/gen/large_random.cpp @@ -0,0 +1,15 @@ +#include "../params.h" +#include "./erdos_renyi.h" +#include "random.h" +#include + +int main(int, char **argv) { + long long seed = atoll(argv[1]); + auto gen = Random(seed); + + int n = gen.uniform(N_MIN, N_MAX); + int m = gen.uniform( + M_MIN, std::min(M_MAX, static_cast(n) * (n - 1) / 2)); + + erdos_renyi(n, m, gen); +} diff --git a/graph/enumerate_triangles/gen/max_random.cpp b/graph/enumerate_triangles/gen/max_random.cpp new file mode 100644 index 000000000..1a187b9d4 --- /dev/null +++ b/graph/enumerate_triangles/gen/max_random.cpp @@ -0,0 +1,13 @@ +#include "../params.h" +#include "./erdos_renyi.h" +#include "random.h" + +int main(int, char **argv) { + long long seed = atoll(argv[1]); + auto gen = Random(seed); + + int n = N_MAX; + int m = M_MAX; + + erdos_renyi(n, m, gen); +} diff --git a/graph/enumerate_triangles/gen/minimum_00.in b/graph/enumerate_triangles/gen/minimum_00.in new file mode 100644 index 000000000..0a5e238c9 --- /dev/null +++ b/graph/enumerate_triangles/gen/minimum_00.in @@ -0,0 +1,3 @@ +2 1 +1 2 +0 1 diff --git a/graph/enumerate_triangles/gen/small_dense.cpp b/graph/enumerate_triangles/gen/small_dense.cpp new file mode 100644 index 000000000..5870d522b --- /dev/null +++ b/graph/enumerate_triangles/gen/small_dense.cpp @@ -0,0 +1,18 @@ +#include "../params.h" +#include "./erdos_renyi.h" +#include "random.h" + +int main(int, char **argv) { + long long seed = atoll(argv[1]); + auto gen = Random(seed); + + int N_MAX_2 = 1; + while (N_MAX_2 < N_MAX && N_MAX_2 * (N_MAX_2 + 1) / 2 <= M_MAX) { + N_MAX_2 += 1; + } + + int n = gen.uniform(N_MIN, N_MAX_2); + int m = gen.uniform(M_MIN, n * (n - 1) / 2); + + erdos_renyi(n, m, gen); +} diff --git a/graph/enumerate_triangles/gen/small_sparse.cpp b/graph/enumerate_triangles/gen/small_sparse.cpp new file mode 100644 index 000000000..b3a9c55c8 --- /dev/null +++ b/graph/enumerate_triangles/gen/small_sparse.cpp @@ -0,0 +1,20 @@ +#include "../params.h" +#include "./erdos_renyi.h" +#include "random.h" +#include + +int main(int, char **argv) { + long long seed = atoll(argv[1]); + auto gen = Random(seed); + + int N_MAX_2 = 1; + while (N_MAX_2 < N_MAX && N_MAX_2 * (N_MAX_2 + 1) / 2 <= M_MAX) { + N_MAX_2 += 1; + } + + int n = gen.uniform(N_MIN, N_MAX_2); + int m = + gen.uniform(M_MIN, std::min({M_MAX, n * 2, n * (n - 1) / 2})); + + erdos_renyi(n, m, gen); +} diff --git a/graph/enumerate_triangles/hash.json b/graph/enumerate_triangles/hash.json new file mode 100644 index 000000000..74d5144fe --- /dev/null +++ b/graph/enumerate_triangles/hash.json @@ -0,0 +1,30 @@ +{ + "example_00.in": "43bd8eff15911662204e476d31b96a8f44884caa0b6754b33273d1d992ba3e3d", + "example_00.out": "a4b2c5db15348c29451e18b8307e5ef81625ea638e807935f39ceaa8d9ac7758", + "large_random_00.in": "564849d9ce38ce19402e0fe93e7c363c87880af9c3d6238f6c27f6c2854a039f", + "large_random_00.out": "60028d69846d40eb9527754dcd93a8e44bffe37356a1df9b0d34d60d41e492b5", + "large_random_01.in": "d89f4b01778842a5b6c21161d65fd4c02bde97950c714d893ff1a61a63230dbb", + "large_random_01.out": "9a271f2a916b0b6ee6cecb2426f0b3206ef074578be55d9bc94f6f3fe3ab86aa", + "large_random_02.in": "6c4b190a4ce85c633e886cde42130d7b3bb323eb857fccb4a984e836071d1927", + "large_random_02.out": "45611109ae4edd6520091229cbb99e31ea877496799b059ad236daf43c670c9e", + "max_random_00.in": "9e1c3aae5d07a0fd3ba5dfaa8476c393c4279bf1b3777336225fa966bfdee2e6", + "max_random_00.out": "f06d429f13c4b39ae9ae0016f4925c41372312540dfa0a2b2c165c9d6f3fbb83", + "max_random_01.in": "34182bc0eef3c24785c3b31086939e8b2cc3152332a1a995729c0e0ad905288a", + "max_random_01.out": "e2d347c0e1dea1c5cd716303eaf2012104c9ec489d32f4f44daf988e36a1b5ef", + "max_random_02.in": "e0caeabe0d3ee50733011ac5e8143ee7ba9c84814d21c538c03336ead707a076", + "max_random_02.out": "bf26c4a8da5ce761e302fa877cd5c3ef055475ecfa9dc01ae20047cc4734ce58", + "minimum_00.in": "5982244103c9d82ae9b5fcdf1e6fcccecb3da77fee1facd7e8736b0602d35448", + "minimum_00.out": "9a271f2a916b0b6ee6cecb2426f0b3206ef074578be55d9bc94f6f3fe3ab86aa", + "small_dense_00.in": "68e6ae6ebae1a3200468c8ff7c76adb1052cdfc9988fe8bbf4fdd589cfa75917", + "small_dense_00.out": "b88c3096b08cd1d111f4192d8b310354c8b6c7e436d4bde35ab1e0b4d76f419e", + "small_dense_01.in": "49fd90cb207d168932d35d4d4c23912a06c9a7f5ff938f867840e9ab84a839e5", + "small_dense_01.out": "f0a03600f373d006727aa449d008d9c565970906fb079b1f6a724ac7fc87ef9d", + "small_dense_02.in": "933ca0590f078d2bb59c0a0b00a5dcf35656de31b3e51ac092dc3806df3c2079", + "small_dense_02.out": "7ff5c7b1d88fc106b16281afbbadb37a10fc6f368a0cd39738422a387613bbb0", + "small_sparse_00.in": "9ed22f92d638eea978925b95e56d99fdf2c5f90f2c669b8c7b22c821dca256d9", + "small_sparse_00.out": "5f5ce23c41b2c2dca216abfdf9d450ac7df652130f6c4a35a91c43153db6dfbe", + "small_sparse_01.in": "fea9e0d6e35cd652acb3f3c4cdee190b05577818bf2cae6377fe7ce91de549bc", + "small_sparse_01.out": "a9374288152d752966cdeed03f26c2687acaece10bd10a618cb7f71054a65efe", + "small_sparse_02.in": "c18141bfdca75f537997264567ee6e68e421b45a21c9f2da40f21af7cd530e2b", + "small_sparse_02.out": "d8606372ea1350af4fb4905771b4753cd790d783615821767c0e91acc208e9a3" +} \ No newline at end of file diff --git a/graph/enumerate_triangles/info.toml b/graph/enumerate_triangles/info.toml new file mode 100644 index 000000000..337dfa142 --- /dev/null +++ b/graph/enumerate_triangles/info.toml @@ -0,0 +1,36 @@ +title = 'Enumerate Triangles' +timelimit = 5.0 +forum = "https://github.com/yosupo06/library-checker-problems/issues/442" + +[[tests]] + name = "example.in" + number = 1 +[[tests]] + name = "minimum.in" + number = 1 +[[tests]] + name = "small_sparse.cpp" + number = 3 +[[tests]] + name = "small_dense.cpp" + number = 3 +[[tests]] + name = "large_random.cpp" + number = 3 +[[tests]] + name = "max_random.cpp" + number = 3 + +[[solutions]] + name = 'naive.cpp' + wrong = true +[[solutions]] + name = 'correct_slow.cpp' + wrong = false + +[params] + N_MIN = 1 + N_MAX = 100_000 + M_MIN = 1 + M_MAX = 100_000 + MOD = 998_244_353 diff --git a/graph/enumerate_triangles/sol/correct.cpp b/graph/enumerate_triangles/sol/correct.cpp new file mode 100644 index 000000000..412265daa --- /dev/null +++ b/graph/enumerate_triangles/sol/correct.cpp @@ -0,0 +1,61 @@ +#include +#include +#include +#include + +int main() { + using i64 = long long; + static constexpr i64 mod = 998244353; + + int n, m; + std::scanf("%d %d", &n, &m); + std::vector xs(n); + for (auto &x : xs) { + scanf("%lld", &x); + } + std::vector> edges(m); + for (auto &e : edges) { + int &u = e.first; + int &v = e.second; + std::scanf("%d %d", &u, &v); + } + + std::vector deg(n, 0); + for (const auto &e : edges) { + int u = e.first; + int v = e.second; + deg[u] += 1; + deg[v] += 1; + } + + std::vector> g(n); + for (const auto &e : edges) { + int u = e.first; + int v = e.second; + if (std::tie(deg[u], u) > std::tie(deg[v], v)) { + std::swap(u, v); + } + g[u].push_back(v); + } + + i64 ans = 0; + std::vector adj(n, false); + for (const auto &e : edges) { + int a = e.first; + int b = e.second; + for (auto c : g[a]) { + adj[c] = true; + } + for (auto c : g[b]) { + if (adj[c]) { + ans += xs[a] * xs[b] % mod * xs[c]; + ans %= mod; + } + } + for (auto c : g[a]) { + adj[c] = false; + } + } + + std::printf("%lld\n", ans); +} diff --git a/graph/enumerate_triangles/sol/correct_slow.cpp b/graph/enumerate_triangles/sol/correct_slow.cpp new file mode 100644 index 000000000..c2d9ccaaa --- /dev/null +++ b/graph/enumerate_triangles/sol/correct_slow.cpp @@ -0,0 +1,58 @@ +#include +#include +#include +#include +#include +#include + +int main() { + using i64 = long long; + static constexpr i64 mod = 998244353; + + int n, m; + std::scanf("%d %d", &n, &m); + std::vector xs(n); + for (auto &x : xs) { + scanf("%lld", &x); + } + std::vector> edges(m); + std::set> eset; + for (auto &e : edges) { + int &u = e.first; + int &v = e.second; + std::scanf("%d %d", &u, &v); + eset.insert(std::minmax(u, v)); + } + + std::vector deg(n, 0); + for (const auto &e : edges) { + int u = e.first; + int v = e.second; + deg[u] += 1; + deg[v] += 1; + } + + std::vector> g(n); + for (const auto &e : edges) { + int u = e.first; + int v = e.second; + if (std::tie(deg[u], u) > std::tie(deg[v], v)) { + std::swap(u, v); + } + g[u].push_back(v); + } + + i64 ans = 0; + for (int a = 0; a < n; ++a) { + for (int b : g[a]) { + for (int c : g[a]) { + if (eset.count({b, c})) { + ans += xs[a] * xs[b] % mod * xs[c]; + ans %= mod; + } + } + } + } + + std::printf("%lld\n", ans); +} diff --git a/graph/enumerate_triangles/sol/naive.cpp b/graph/enumerate_triangles/sol/naive.cpp new file mode 100644 index 000000000..d63b86d44 --- /dev/null +++ b/graph/enumerate_triangles/sol/naive.cpp @@ -0,0 +1,37 @@ +#include +#include +#include +#include +#include + +int main() { + using i64 = long long; + static constexpr i64 mod = 998244353; + + int n, m; + std::scanf("%d %d", &n, &m); + std::vector xs(n); + for (auto &x : xs) { + scanf("%lld", &x); + } + std::set> edges; + for (int i = 0; i < m; ++i) { + int u, v; + std::scanf("%d %d", &u, &v); + edges.insert(std::minmax({u, v})); + } + + i64 ans = 0; + for (int a = 0; a < n; ++a) { + for (int b = 0; b < a; ++b) { + for (int c = 0; c < b; ++c) { + if (edges.count({c, b}) && edges.count({c, a}) && edges.count({b, a})) { + ans += xs[a] * xs[b] % mod * xs[c]; + ans %= mod; + } + } + } + } + + std::printf("%lld\n", ans); +} diff --git a/graph/enumerate_triangles/task.md b/graph/enumerate_triangles/task.md new file mode 100644 index 000000000..c79a1960a --- /dev/null +++ b/graph/enumerate_triangles/task.md @@ -0,0 +1,60 @@ +## @{keyword.statement} + +@{lang.en} +You are given a simple undirected graph, consisting of $N$ vertices and $M$ edges. +The $i$-th edge is $\lbrace u_i, v_i \rbrace$. +Each vertex has an integer value, and the value of $i$ th vertex is $x_i$. + +Three vertices $a, b, c$ connected by three edges $\lbrace a, b \rbrace, \lbrace a, c \rbrace, \lbrace b, c \rbrace$ are called triangle. +Find the sum of $x_a x_b x_c$ over all triangles, and print the sum modulo $@{param.MOD}$ . + +@{lang.ja} +$N$ 頂点 $M$ 辺の単純無向グラフが与えられます。 +$i$ 番目の辺は $\lbrace u_i, v_i \rbrace$ です。 +各頂点 $i$ には整数 $x_i$ が割り当てられています。 + +3 頂点 $a, b, c$ であって辺 $\lbrace a, b \rbrace, \lbrace a, c \rbrace, \lbrace b, c \rbrace$ が全て存在するものを triangle と呼びます。 +全ての triangle についての $x_a x_b x_c$ の和を $@{param.MOD}$ で割った余りを求めてください。 + +@{lang.end} + +## @{keyword.constraints} + +- $@{param.N_MIN} \le N \le @{param.N_MAX}$ +- $@{param.M_MIN} \le M \le @{param.M_MAX}$ +- $0 \le x_i \lt @{param.MOD}$ +- $0 \le u_i \lt N$ +- $0 \le v_i \lt N$ +- $u_i \neq v_j$ +- $\lbrace u_i, v_i \rbrace \neq \lbrace u_j, v_j \rbrace \ (i \neq j)$ + +## @{keyword.input} + +``` +$N$ $M$ +$x_0$ $x_1$ $\ldots$ $x_{N-1}$ +$u_0$ $v_0$ +$u_1$ $v_1$ +$\vdots$ +$u_{M-1}$ $v_{M-1}$ +``` + +## @{keyword.output} + +``` +$A$ +``` + +## @{keyword.sample} + +@{example.example_00} + +@{lang.en} +$0, 2, 3$ and $1, 2, 3$ are triangles. +Print $36$, which is the result of $1 \cdot 3 \cdot 4 + 2 \cdot 3 \cdot 4 \bmod @{param.MOD}$ . + +@{lang.ja} +$0, 2, 3$ 及び $1, 2, 3$ が triangle です。 +$1 \cdot 3 \cdot 4 + 2 \cdot 3 \cdot 4$ を $@{param.MOD}$ で割った余りである $36$ を出力します。 + +@{lang.end} diff --git a/graph/enumerate_triangles/verifier.cpp b/graph/enumerate_triangles/verifier.cpp new file mode 100644 index 000000000..19fa77c35 --- /dev/null +++ b/graph/enumerate_triangles/verifier.cpp @@ -0,0 +1,34 @@ +#include "params.h" +#include "testlib.h" +#include +#include +#include + +int main() { + registerValidation(); + + int n = inf.readInt(N_MIN, N_MAX); + inf.readSpace(); + int m = inf.readInt(M_MIN, M_MAX); + inf.readChar('\n'); + for (int i = 0; i < n; ++i) { + inf.readInt(0, MOD - 1); + if (i != n - 1) { + inf.readSpace(); + } else { + inf.readChar('\n'); + } + } + + std::set> edges; + for (int i = 0; i < m; ++i) { + int u = inf.readInt(0, n - 1); + inf.readSpace(); + int v = inf.readInt(0, n - 1); + ensure(u != v); + ensure(edges.insert(std::minmax(u, v)).second); + inf.readChar('\n'); + } + + inf.readEof(); +} From 47a7dc9e0889c4beabc47b313017feeba09b8c4a Mon Sep 17 00:00:00 2001 From: noshi91 Date: Thu, 7 May 2020 00:22:08 +0900 Subject: [PATCH 2/2] fix task.md --- graph/enumerate_triangles/task.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/graph/enumerate_triangles/task.md b/graph/enumerate_triangles/task.md index c79a1960a..cd1567500 100644 --- a/graph/enumerate_triangles/task.md +++ b/graph/enumerate_triangles/task.md @@ -5,7 +5,7 @@ You are given a simple undirected graph, consisting of $N$ vertices and $M$ edge The $i$-th edge is $\lbrace u_i, v_i \rbrace$. Each vertex has an integer value, and the value of $i$ th vertex is $x_i$. -Three vertices $a, b, c$ connected by three edges $\lbrace a, b \rbrace, \lbrace a, c \rbrace, \lbrace b, c \rbrace$ are called triangle. +Three vertices $a, b, c (a \lt b \lt c)$ connected by three edges $\lbrace a, b \rbrace, \lbrace a, c \rbrace, \lbrace b, c \rbrace$ are called triangle. Find the sum of $x_a x_b x_c$ over all triangles, and print the sum modulo $@{param.MOD}$ . @{lang.ja} @@ -13,7 +13,7 @@ $N$ 頂点 $M$ 辺の単純無向グラフが与えられます。 $i$ 番目の辺は $\lbrace u_i, v_i \rbrace$ です。 各頂点 $i$ には整数 $x_i$ が割り当てられています。 -3 頂点 $a, b, c$ であって辺 $\lbrace a, b \rbrace, \lbrace a, c \rbrace, \lbrace b, c \rbrace$ が全て存在するものを triangle と呼びます。 +3 頂点 $a, b, c (a \lt b \lt c)$ であって辺 $\lbrace a, b \rbrace, \lbrace a, c \rbrace, \lbrace b, c \rbrace$ が全て存在するものを triangle と呼びます。 全ての triangle についての $x_a x_b x_c$ の和を $@{param.MOD}$ で割った余りを求めてください。 @{lang.end}