diff --git a/linear_algebra/system_of_linear_equations_mod_2/checker.cpp b/linear_algebra/system_of_linear_equations_mod_2/checker.cpp new file mode 100644 index 00000000..031dd830 --- /dev/null +++ b/linear_algebra/system_of_linear_equations_mod_2/checker.cpp @@ -0,0 +1,89 @@ +#include +#include +#include +#include +#include "testlib.h" + +using namespace std; +using BS = bitset<4096>; + +int N, M; +BS A[4096]; +BS b; + +BS evaluate(BS x) { + BS y; + for (int i = 0; i < N; ++i) { + int cnt = (x & A[i]).count(); + y[i] = cnt % 2; + } + return y; +} + +int matrix_rank(vector a) { + int N = a.size(); + int rk = 0; + for (int j = 0; j < M; ++j) { + if (rk == N) break; + if (!a[rk][j]) { + for (int i = rk + 1; i < N; ++i) { + if (a[i][j]) { + swap(a[rk], a[i]); + break; + } + } + } + if (!a[rk][j]) continue; + for (int i = rk + 1; i < N; ++i) { + if (a[i][j]) { a[i] ^= a[rk]; } + } + ++rk; + } + return rk; +} + +int get_rank(InStream& stream) { + int r = stream.readInt(-1, M); + if (r == -1) return -1; + vector mat; + + for (int k = 0; k < r + 1; ++k) { + string S = stream.readToken(); + stream.ensure(int(S.size()) == M); + for (auto& ch: S) stream.ensure(ch == '0' || ch == '1'); + BS x; + for (int j = 0; j < M; ++j) x[j] = (S[j] - '0'); + BS y = evaluate(x); + if (k == 0) { + for (int i = 0; i < N; ++i) { stream.ensure(y[i] == b[i]); } + } else { + for (int i = 0; i < N; ++i) { stream.ensure(y[i] == false); } + mat.emplace_back(x); + } + } + stream.ensure(matrix_rank(mat) == r); + return r; +} + +int main(int argc, char* argv[]) { + registerTestlibCmd(argc, argv); + // read input + N = inf.readInt(); + M = inf.readInt(); + for (int i = 0; i < N; ++i) { + string S = inf.readToken(); + for (int j = 0; j < M; ++j) A[i][j] = (S[j] - '0'); + } + string S = inf.readToken(); + for (int i = 0; i < N; ++i) b[i] = (S[i] - '0'); + + int k_ans = get_rank(ans); + int k_ouf = get_rank(ouf); + + if (k_ans == -1 && k_ouf == -1) { quitf(_ok, "OK No solution"); } + if (k_ans != -1 && k_ouf == -1) { quitf(_wa, "WA you cannot find solution"); } + if (k_ans == -1 && k_ouf != -1) { quitf(_fail, "Judge cannot find solution"); } + if (k_ans > k_ouf) { quitf(_wa, "There are more solutions"); } + if (k_ans < k_ouf) { quitf(_fail, "What happened?"); } + quitf(_ok, "OK"); +} diff --git a/linear_algebra/system_of_linear_equations_mod_2/gen/base.hpp b/linear_algebra/system_of_linear_equations_mod_2/gen/base.hpp new file mode 100644 index 00000000..6cc3341b --- /dev/null +++ b/linear_algebra/system_of_linear_equations_mod_2/gen/base.hpp @@ -0,0 +1,73 @@ +#include +#include +#include "random.h" + +using namespace std; +using BS = bitset<4096>; + +void out(int n, int m, vector A, BS b) { + auto out_BS = [&](int n, BS x) -> void { + string S(n, '?'); + for (int i = 0; i < n; ++i) S[i] = (x[i] ? '1' : '0'); + printf("%s\n", S.c_str()); + }; + printf("%d %d\n", n, m); + for (int i = 0; i < n; ++i) out_BS(m, A[i]); + out_BS(n, b); +} + +void gen_yes(int n, int m, int r, Random &gen) { + assert(r <= m && r <= n); + vector a(n); + for (int i = 0; i < r; ++i) { + for (int j = 0; j < m; ++j) { a[i][j] = gen.uniform_bool(); } + } + for (int i = r; i < n; ++i) { + for (int k = 0; k < r; ++k) { + if (gen.uniform_bool()) a[i] ^= a[k]; + } + } + // shuffle + gen.shuffle(a.begin(), a.end()); + + BS x; + for (int i = 0; i < m; ++i) x[i] = gen.uniform_bool(); + BS y; + for (int i = 0; i < n; ++i) { y[i] = (a[i] & x).count() % 2; } + out(n, m, a, y); +} + +void gen_no(int n, int m, int r, Random &gen) { + assert(r <= m && r < n); + vector a(n); + for (int i = 0; i < r; ++i) { + for (int j = 0; j < m; ++j) { a[i][j] = gen.uniform_bool(); } + } + + BS y; + for (int i = 0; i < n; ++i) { y[i] = gen.uniform_bool(); } + // at least one 1 + y[gen.uniform(r, n - 1)] = 1; + + for (int i = r; i < n; ++i) { + for (int k = 0; k < r; ++k) { + if (gen.uniform_bool()) { + a[i] ^= a[k]; + y[i] = y[i] ^ y[k]; + } + } + } + + // shuffle + vector new_idx(n); + for (int i = 0; i < n; ++i) new_idx[i] = i; + gen.shuffle(new_idx.begin(), new_idx.end()); + vector new_a(n); + BS new_y; + for (int i = 0; i < n; ++i) { + new_a[new_idx[i]] = a[i]; + new_y[new_idx[i]] = y[i]; + } + + out(n, m, new_a, new_y); +} diff --git a/linear_algebra/system_of_linear_equations_mod_2/gen/example_00.in b/linear_algebra/system_of_linear_equations_mod_2/gen/example_00.in new file mode 100644 index 00000000..867988bc --- /dev/null +++ b/linear_algebra/system_of_linear_equations_mod_2/gen/example_00.in @@ -0,0 +1,5 @@ +3 3 +101 +011 +110 +011 diff --git a/linear_algebra/system_of_linear_equations_mod_2/gen/example_01.in b/linear_algebra/system_of_linear_equations_mod_2/gen/example_01.in new file mode 100644 index 00000000..c4700cfb --- /dev/null +++ b/linear_algebra/system_of_linear_equations_mod_2/gen/example_01.in @@ -0,0 +1,5 @@ +3 3 +101 +011 +110 +111 diff --git a/linear_algebra/system_of_linear_equations_mod_2/gen/example_02.in b/linear_algebra/system_of_linear_equations_mod_2/gen/example_02.in new file mode 100644 index 00000000..83755b9a --- /dev/null +++ b/linear_algebra/system_of_linear_equations_mod_2/gen/example_02.in @@ -0,0 +1,3 @@ +1 3 +111 +1 diff --git a/linear_algebra/system_of_linear_equations_mod_2/gen/max_lowrank.cpp b/linear_algebra/system_of_linear_equations_mod_2/gen/max_lowrank.cpp new file mode 100644 index 00000000..139efc80 --- /dev/null +++ b/linear_algebra/system_of_linear_equations_mod_2/gen/max_lowrank.cpp @@ -0,0 +1,20 @@ +#include +#include "random.h" +#include "../params.h" +#include "base.hpp" + +using namespace std; + +int main(int, char* argv[]) { + long long seed = atoll(argv[1]); + auto gen = Random(seed); + + int rs[] = {1, 10, 100, 1000, 4000}; + + int n = N_MAX; + int m = M_MAX; + int r = rs[seed % 5]; + if (seed % 2 == 0) gen_yes(n, m, r, gen); + if (seed % 2 == 1) gen_no(n, m, r, gen); + return 0; +} diff --git a/linear_algebra/system_of_linear_equations_mod_2/gen/max_random.cpp b/linear_algebra/system_of_linear_equations_mod_2/gen/max_random.cpp new file mode 100644 index 00000000..07f66d2b --- /dev/null +++ b/linear_algebra/system_of_linear_equations_mod_2/gen/max_random.cpp @@ -0,0 +1,27 @@ +#include +#include "random.h" +#include "../params.h" + +using namespace std; + +int main(int, char* argv[]) { + long long seed = atoll(argv[1]); + auto gen = Random(seed); + + int n = N_MAX; + int m = M_MAX; + auto random_01_str = [&](int n) -> string { + string S(n, '?'); + for (int i = 0; i < n; ++i) S[i] = '0' + gen.uniform(0, 1); + return S; + }; + + printf("%d %d\n", n, m); + for (int i = 0; i < n; i++) { + string S = random_01_str(m); + printf("%s\n", S.c_str()); + } + string S = random_01_str(n); + printf("%s\n", S.c_str()); + return 0; +} diff --git a/linear_algebra/system_of_linear_equations_mod_2/gen/max_small.cpp b/linear_algebra/system_of_linear_equations_mod_2/gen/max_small.cpp new file mode 100644 index 00000000..c6767995 --- /dev/null +++ b/linear_algebra/system_of_linear_equations_mod_2/gen/max_small.cpp @@ -0,0 +1,18 @@ +#include +#include "random.h" +#include "../params.h" +#include "base.hpp" + +using namespace std; + +int main(int, char* argv[]) { + long long seed = atoll(argv[1]); + auto gen = Random(seed); + + int n = N_MAX; + int m = gen.uniform(2, 10); + int r = gen.uniform(1, min(n, m) - 1); + if (seed % 2 == 0) gen_yes(n, m, r, gen); + if (seed % 2 == 1) gen_no(n, m, r, gen); + return 0; +} diff --git a/linear_algebra/system_of_linear_equations_mod_2/gen/random.cpp b/linear_algebra/system_of_linear_equations_mod_2/gen/random.cpp new file mode 100644 index 00000000..75c041b7 --- /dev/null +++ b/linear_algebra/system_of_linear_equations_mod_2/gen/random.cpp @@ -0,0 +1,27 @@ +#include +#include "random.h" +#include "../params.h" + +using namespace std; + +int main(int, char* argv[]) { + long long seed = atoll(argv[1]); + auto gen = Random(seed); + + int n = gen.uniform(1, N_MAX); + int m = gen.uniform(1, M_MAX); + auto random_01_str = [&](int n) -> string { + string S(n, '?'); + for (int i = 0; i < n; ++i) S[i] = '0' + gen.uniform(0, 1); + return S; + }; + + printf("%d %d\n", n, m); + for (int i = 0; i < n; i++) { + string S = random_01_str(m); + printf("%s\n", S.c_str()); + } + string S = random_01_str(n); + printf("%s\n", S.c_str()); + return 0; +} diff --git a/linear_algebra/system_of_linear_equations_mod_2/gen/small_max.cpp b/linear_algebra/system_of_linear_equations_mod_2/gen/small_max.cpp new file mode 100644 index 00000000..a06e8e40 --- /dev/null +++ b/linear_algebra/system_of_linear_equations_mod_2/gen/small_max.cpp @@ -0,0 +1,18 @@ +#include +#include "random.h" +#include "../params.h" +#include "base.hpp" + +using namespace std; + +int main(int, char* argv[]) { + long long seed = atoll(argv[1]); + auto gen = Random(seed); + + int n = gen.uniform(2, 10); + int m = M_MAX; + int r = gen.uniform(1, min(n, m) - 1); + if (seed % 2 == 0) gen_yes(n, m, r, gen); + if (seed % 2 == 1) gen_no(n, m, r, gen); + return 0; +} diff --git a/linear_algebra/system_of_linear_equations_mod_2/gen/small_random.cpp b/linear_algebra/system_of_linear_equations_mod_2/gen/small_random.cpp new file mode 100644 index 00000000..076ff328 --- /dev/null +++ b/linear_algebra/system_of_linear_equations_mod_2/gen/small_random.cpp @@ -0,0 +1,27 @@ +#include +#include "random.h" +#include "../params.h" + +using namespace std; + +int main(int, char* argv[]) { + long long seed = atoll(argv[1]); + auto gen = Random(seed); + + int n = gen.uniform(1, 3); + int m = gen.uniform(1, 3); + auto random_01_str = [&](int n) -> string { + string S(n, '?'); + for (int i = 0; i < n; ++i) S[i] = '0' + gen.uniform(0, 1); + return S; + }; + + printf("%d %d\n", n, m); + for (int i = 0; i < n; i++) { + string S = random_01_str(m); + printf("%s\n", S.c_str()); + } + string S = random_01_str(n); + printf("%s\n", S.c_str()); + return 0; +} diff --git a/linear_algebra/system_of_linear_equations_mod_2/gen/smallest_00.in b/linear_algebra/system_of_linear_equations_mod_2/gen/smallest_00.in new file mode 100644 index 00000000..8550cfd6 --- /dev/null +++ b/linear_algebra/system_of_linear_equations_mod_2/gen/smallest_00.in @@ -0,0 +1,3 @@ +1 1 +0 +0 diff --git a/linear_algebra/system_of_linear_equations_mod_2/gen/smallest_01.in b/linear_algebra/system_of_linear_equations_mod_2/gen/smallest_01.in new file mode 100644 index 00000000..82e1ed21 --- /dev/null +++ b/linear_algebra/system_of_linear_equations_mod_2/gen/smallest_01.in @@ -0,0 +1,3 @@ +1 1 +0 +1 diff --git a/linear_algebra/system_of_linear_equations_mod_2/gen/smallest_02.in b/linear_algebra/system_of_linear_equations_mod_2/gen/smallest_02.in new file mode 100644 index 00000000..56ebc3a9 --- /dev/null +++ b/linear_algebra/system_of_linear_equations_mod_2/gen/smallest_02.in @@ -0,0 +1,3 @@ +1 1 +1 +0 diff --git a/linear_algebra/system_of_linear_equations_mod_2/gen/smallest_03.in b/linear_algebra/system_of_linear_equations_mod_2/gen/smallest_03.in new file mode 100644 index 00000000..fa06f247 --- /dev/null +++ b/linear_algebra/system_of_linear_equations_mod_2/gen/smallest_03.in @@ -0,0 +1,3 @@ +1 1 +1 +1 diff --git a/linear_algebra/system_of_linear_equations_mod_2/hash.json b/linear_algebra/system_of_linear_equations_mod_2/hash.json new file mode 100644 index 00000000..207ddd3a --- /dev/null +++ b/linear_algebra/system_of_linear_equations_mod_2/hash.json @@ -0,0 +1,74 @@ +{ + "example_00.in": "6063634b3c8f31aaf3078a8c22c3cdd8b53e4050846df4abd9d8f80cd43a7ef7", + "example_00.out": "e5ba645c12ed5697234f5d87e0cee43b0bd05dc5c8dd5026773b9bbc4c84a820", + "example_01.in": "fd2399647e31fcecbd55921de8aac02c20867fb3fa06c84abeffd4de72370b23", + "example_01.out": "ee3aa64bb94a50845d5024cd4bd20202a4567aed5cd5328c0d97e9920775fc28", + "example_02.in": "cdb150eaa586f422a1e0429b7189b4c3818edda13433e81a51e326e4265fe037", + "example_02.out": "2a7863cc0aeace6e8a08f3c5c2f564c685367bc60c65b1a65b211e6f21a28204", + "max_lowrank_00.in": "6638c04e8e68603cf0b5793646e5cd97da74845a2e698fcbe4926153e0b034f7", + "max_lowrank_00.out": "1cbff4f7984fa485b4bafa2e7cb87760c081628850b437fa2ee6db792bdaa41f", + "max_lowrank_01.in": "1786aa087f73e997aa44d97d6fba6ed00105968c9d630c9374f316e43f91f6fb", + "max_lowrank_01.out": "ee3aa64bb94a50845d5024cd4bd20202a4567aed5cd5328c0d97e9920775fc28", + "max_lowrank_02.in": "bbe5a65f8b0b606dcb1f30e52a446f57b9bdd14fee234e58c2187de7fe0b5544", + "max_lowrank_02.out": "95c6e77f883f3251cf7086e9974ae5dacf90a4460971735c0de7828efb72ce4f", + "max_lowrank_03.in": "aab930335a5a484401015450290e5f2f37a08b6a2d09cde429ae659ac77c1789", + "max_lowrank_03.out": "ee3aa64bb94a50845d5024cd4bd20202a4567aed5cd5328c0d97e9920775fc28", + "max_lowrank_04.in": "8ee5123b7f3cb3a852d83ff13b9f47badb42f21b322d10ead350c32005854b52", + "max_lowrank_04.out": "c6dde9b67e9ede353faaff3093c1a3889f058f6a37802a5fff5607dd64a9af6e", + "max_lowrank_05.in": "3d4e7b300e10337c68a607944df0980d73f0919191b86fd8d15693be3a446092", + "max_lowrank_05.out": "ee3aa64bb94a50845d5024cd4bd20202a4567aed5cd5328c0d97e9920775fc28", + "max_lowrank_06.in": "119dcae58eb863729ac38fa8e815bcba0dc4b790e110fd1dd787b9720b627a4a", + "max_lowrank_06.out": "1092c7fc6c2d6a0f0d35bd04a776e906b8ff376015c5d912380d93fa81ead70a", + "max_lowrank_07.in": "a70ce08bda2a9f2e1b493ecc7600a6c54f65eba7de515c76a2573a1d31f728ff", + "max_lowrank_07.out": "ee3aa64bb94a50845d5024cd4bd20202a4567aed5cd5328c0d97e9920775fc28", + "max_lowrank_08.in": "a0c42ec11aae679d3fc0a57eaa7864c0a0b26c156daf8f1f32192ae12292cda7", + "max_lowrank_08.out": "870d275ec5452b46a76b780214dd72aa6139be340f09fd39b6666b8ff5395e27", + "max_lowrank_09.in": "b219971c910a4e9d16146761975ba599dd6671fb565262bc61f5d1006e304b51", + "max_lowrank_09.out": "ee3aa64bb94a50845d5024cd4bd20202a4567aed5cd5328c0d97e9920775fc28", + "max_random_00.in": "e6e5a5f028dd1e1ac24bd8cae64c67b022c2da23c667e545bc8bdb30dbf382c3", + "max_random_00.out": "ee3aa64bb94a50845d5024cd4bd20202a4567aed5cd5328c0d97e9920775fc28", + "max_random_01.in": "e4eab8c7c8920d14b4db35b38ca8e50e6c6fb35ec13f0fdcc3a25e1d58e3188a", + "max_random_01.out": "eebb9700465e9fd322f5916a3e3a16082deac8ee7bf561a977c6483aa29d61d6", + "max_random_02.in": "10ba78d1ab65588fd20c4b157b96859e87a6f49031500aafbc0e54421086e1c1", + "max_random_02.out": "87830da28ca0340dd748484b4ed8e87d7a392412cbde7ac390be147255757769", + "max_random_03.in": "9a2dacdc0a7b53adeea8cb59a44906b488a0aa76b82e957e0317c56afde9c2ec", + "max_random_03.out": "ee3aa64bb94a50845d5024cd4bd20202a4567aed5cd5328c0d97e9920775fc28", + "max_random_04.in": "0bb65fc99cb2a29a0b82e11a9502b0ecc50e8d5b22904fa998cd66b593a29b61", + "max_random_04.out": "a751f1e4acb5cfc16d7daabcc4c6073b675dd9e20e8094e9cd8e903a83e7060e", + "max_small_00.in": "423f3ba9fd2b89970fd099f1a98e78add8c8702f9996662a375417cbf98a1005", + "max_small_00.out": "2b3fcb7b98f30fd92c50d331255c08440ed9c423a5527f7caf80018139f6a07c", + "max_small_01.in": "37bbd1cb74cc6b66d8afbdf3f6fe34ee87d48ea80d9598cd9ccc6f6b41a6d504", + "max_small_01.out": "ee3aa64bb94a50845d5024cd4bd20202a4567aed5cd5328c0d97e9920775fc28", + "random_00.in": "611c05258c9bed06038e9e667a33f77ce649ee071327c68e4e302e93428d1cfc", + "random_00.out": "527bee4215a969e7872cef01ed103212834fa4bf4128acd5de4ef21794a9510a", + "random_01.in": "b577ffaa423711baf18e534360f5ce0e25a51c4e5eda44962138778abe6b82c7", + "random_01.out": "3af7b14001f9ebf2361ce50909487183d168cecefe308892cb8e67cedc95325f", + "random_02.in": "ecb7e49a76a27b5bfe45673cb205655c1a5a21b10740a2b556b2d35e1e14cf27", + "random_02.out": "5e01a5dea71a66d368078237a6c6b4f6006424ad9c2b0ac7329d8175e58fa4c7", + "random_03.in": "fe3cc828676cd6ffb0a1266fbf99278d194981540b776d5df239454c30248f07", + "random_03.out": "ee3aa64bb94a50845d5024cd4bd20202a4567aed5cd5328c0d97e9920775fc28", + "random_04.in": "af3c71dd2b28cfbc25b8de3f29760b9867f4ee1019e6660959c87e8464f81aac", + "random_04.out": "ee3aa64bb94a50845d5024cd4bd20202a4567aed5cd5328c0d97e9920775fc28", + "small_max_00.in": "89ea26b22a2432afa0ada82090b1608e90521dbbbc921ab16e9f59ff685ae8cb", + "small_max_00.out": "bfbfd40999eb4e2006d88888007c749b982dd1a6398e64d77fc5f863d19b6060", + "small_max_01.in": "f5574faa4a2954961a68a82c298699c4d925da7e5d4d51a633fa8dd9b3e355d7", + "small_max_01.out": "ee3aa64bb94a50845d5024cd4bd20202a4567aed5cd5328c0d97e9920775fc28", + "small_random_00.in": "63f62781d1b4d9da4e62c279b3fa00adf84b016a817f0c83020c90bdffe5c492", + "small_random_00.out": "e30db10f9e3d4cb0abc5e29aeebbeaccedb49322abf4905f0de9cde81cc69bf4", + "small_random_01.in": "431375d2119248e201ee4bc87af17b19a60ec90859cdb7b00a1658cd9ddd6f04", + "small_random_01.out": "fbd3659d33448e458de8fd2972b27a061ddd037a1dd08f2e5e88d27862c0d5d7", + "small_random_02.in": "0c576d991bb5a27c47cbbdd5e5812d1cc91f18a3ca7ccde4d76ac7cf33b44e72", + "small_random_02.out": "ee3aa64bb94a50845d5024cd4bd20202a4567aed5cd5328c0d97e9920775fc28", + "small_random_03.in": "9142de3ca7f55a060928c24bf06a2bd8d78274a1aef486291cac3ca996353f36", + "small_random_03.out": "feb8513038ebe210da5e78db6025f2cc021956be75402b9f364ea17569f2e8f0", + "small_random_04.in": "23fb973368a17ad6b34c11df9eccd75362a91679050977591187372215f70fa6", + "small_random_04.out": "44bc3f637732558aeee7211e96d5b372fcdd4a441a95aec1fc183677fc41f55c", + "smallest_00.in": "e143ec05631e8515c810286dceeeaa93d4d433bd83ed980079e7da1958c8a17e", + "smallest_00.out": "a714acf0208a1a2e55902965ae577dcc30aa50e1fb1ba16a525e7f5cca653428", + "smallest_01.in": "1bf5777e213ac99383a7b880f4508fb256a7fe85aa466378b375908f653d489e", + "smallest_01.out": "ee3aa64bb94a50845d5024cd4bd20202a4567aed5cd5328c0d97e9920775fc28", + "smallest_02.in": "46964811c1e5d970fb6adebde76da0dcf1d0954921d349575538d34b90bfee86", + "smallest_02.out": "52f96c26a39ed25108a6db43d6e11c6051eba8a498a5baab1891adfa7ac7c262", + "smallest_03.in": "8b88a21ef03528d1b1eb90b24e9a05cb51fc2f935555f94f3999f2f6467ddf0f", + "smallest_03.out": "82c1315e6c757f33c4a77ca58b2a184f5a88614470c05ec77f3d28918db6b8ae" +} \ No newline at end of file diff --git a/linear_algebra/system_of_linear_equations_mod_2/info.toml b/linear_algebra/system_of_linear_equations_mod_2/info.toml new file mode 100644 index 00000000..a183b699 --- /dev/null +++ b/linear_algebra/system_of_linear_equations_mod_2/info.toml @@ -0,0 +1,32 @@ +title = 'System of Linear Equations (Mod 2)' +timelimit = 5.0 +forum = "https://github.com/yosupo06/library-checker-problems/issues/896" + +[[tests]] + name = "example.in" + number = 3 +[[tests]] + name = "smallest.in" + number = 4 +[[tests]] + name = "small_random.cpp" + number = 5 +[[tests]] + name = "random.cpp" + number = 5 +[[tests]] + name = "max_random.cpp" + number = 5 +[[tests]] + name = "max_small.cpp" + number = 2 +[[tests]] + name = "small_max.cpp" + number = 2 +[[tests]] + name = "max_lowrank.cpp" + number = 10 + +[params] + N_MAX = 4096 + M_MAX = 4096 diff --git a/linear_algebra/system_of_linear_equations_mod_2/sol/correct.cpp b/linear_algebra/system_of_linear_equations_mod_2/sol/correct.cpp new file mode 100644 index 00000000..04417fd3 --- /dev/null +++ b/linear_algebra/system_of_linear_equations_mod_2/sol/correct.cpp @@ -0,0 +1,193 @@ +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +using ll = long long; +using u32 = unsigned int; +using u64 = unsigned long long; + +using pi = pair; +using vi = vector; +template +using vc = vector; +template +using vvc = vector>; + +#define vv(type, name, h, ...) vector> name(h, vector(__VA_ARGS__)) + +#define FOR1(a) for (ll _ = 0; _ < ll(a); ++_) +#define FOR2(i, a) for (ll i = 0; i < ll(a); ++i) +#define FOR3(i, a, b) for (ll i = a; i < ll(b); ++i) +#define FOR4(i, a, b, c) for (ll i = a; i < ll(b); i += (c)) +#define FOR1_R(a) for (ll i = (a)-1; i >= ll(0); --i) +#define FOR2_R(i, a) for (ll i = (a)-1; i >= ll(0); --i) +#define FOR3_R(i, a, b) for (ll i = (b)-1; i >= ll(a); --i) +#define overload4(a, b, c, d, e, ...) e +#define overload3(a, b, c, d, ...) d +#define FOR(...) overload4(__VA_ARGS__, FOR4, FOR3, FOR2, FOR1)(__VA_ARGS__) +#define FOR_R(...) overload3(__VA_ARGS__, FOR3_R, FOR2_R, FOR1_R)(__VA_ARGS__) + +#define all(x) x.begin(), x.end() +#define len(x) ll(x.size()) +#define elif else if + +#define eb emplace_back +#define mp make_pair +#define mt make_tuple +#define fi first +#define se second + +int topbit(u64 x) { return (x == 0 ? -1 : 63 - __builtin_clzll(x)); } +int lowbit(u64 x) { return (x == 0 ? -1 : __builtin_ctzll(x)); } + +template +T SUM(const vector &A) { + T sm = 0; + for (auto &&a: A) sm += a; + return sm; +} + +template +inline bool chmax(T &a, const S &b) { + return (a < b ? a = b, 1 : 0); +} +template +inline bool chmin(T &a, const S &b) { + return (a > b ? a = b, 1 : 0); +} + +struct My_Bitset { + using T = My_Bitset; + int N; + vc dat; + + // x で埋める + My_Bitset(int N = 0, int x = 0) : N(N) { + assert(x == 0 || x == 1); + u64 v = (x == 0 ? 0 : -1); + dat.assign((N + 63) >> 6, v); + if (N) dat.back() >>= (64 * len(dat) - N); + } + + int size() { return N; } + + class Proxy { + public: + Proxy(vc &d, int i) : dat(d), index(i) {} + operator bool() const { return (dat[index >> 6] >> (index & 63)) & 1; } + + Proxy &operator=(u64 value) { + dat[index >> 6] &= ~(u64(1) << (index & 63)); + dat[index >> 6] |= (value & 1) << (index & 63); + return *this; + } + void flip() { + dat[index >> 6] ^= (u64(1) << (index & 63)); // XOR to flip the bit + } + + private: + vc &dat; + int index; + }; + + Proxy operator[](int i) { return Proxy(dat, i); } + + T &operator^=(const T &p) { + assert(N == p.N); + FOR(i, len(dat)) dat[i] ^= p.dat[i]; + return *this; + } + T operator^(const T &p) const { return T(*this) ^= p; } + + static string TO_STR[256]; + string to_string() const { + if (TO_STR[0].empty()) precompute(); + string S; + for (auto &x: dat) { FOR(i, 8) S += TO_STR[(x >> (8 * i) & 255)]; } + S.resize(N); + return S; + } + + static void precompute() { + FOR(s, 256) { + string x; + FOR(i, 8) x += '0' + (s >> i & 1); + TO_STR[s] = x; + } + } +}; +string My_Bitset::TO_STR[256]; + +vc solve_linear(int n, int m, vc A, My_Bitset b) { + using BS = My_Bitset; + assert(len(b) == n); + int rk = 0; + FOR(j, m) { + if (rk == n) break; + FOR(i, rk + 1, n) if (A[i][j]) { + swap(A[rk], A[i]); + if (b[rk] != b[i]) b[rk] = !b[rk], b[i] = !b[i]; + break; + } + if (!A[rk][j]) continue; + FOR(i, n) if (i != rk) { + if (A[i][j]) { b[i] = b[i] ^ b[rk], A[i] = A[i] ^ A[rk]; } + } + ++rk; + } + FOR(i, rk, n) if (b[i]) return {}; + vc res(1, BS(m)); + + vc pivot(m, -1); + int p = 0; + FOR(i, rk) { + while (!A[i][p]) ++p; + res[0][p] = bool(b[i]), pivot[p] = i; + } + FOR(j, m) if (pivot[j] == -1) { + BS x(m); + x[j] = 1; + FOR(k, j) if (pivot[k] != -1 && A[pivot[k]][j]) x[k] = 1; + res.eb(x); + } + return res; +} + +void solve() { + int N, M; + scanf("%d %d\n", &N, &M); + using BS = My_Bitset; + auto get = [&](int n) -> BS { + BS x(n); + char c; + for (int i = 0; i < n; ++i) { + scanf("%c", &c); + x[i] = c - '0'; + } + scanf("%c", &c); + assert(c == '\n'); + return x; + }; + vc A(N); + FOR(i, N) A[i] = get(M); + BS b = get(N); + auto ANS = solve_linear(N, M, A, b); + if (ANS.empty()) { + printf("-1\n"); + return; + } + int R = len(ANS) - 1; + printf("%d\n", R); + for (auto &x: ANS) { + string ans = x.to_string(); + printf("%s\n", ans.c_str()); + } +} + +signed main() { solve(); } diff --git a/linear_algebra/system_of_linear_equations_mod_2/task.md b/linear_algebra/system_of_linear_equations_mod_2/task.md new file mode 100644 index 00000000..6e44427a --- /dev/null +++ b/linear_algebra/system_of_linear_equations_mod_2/task.md @@ -0,0 +1,72 @@ +## @{keyword.statement} + +@{lang.en} + +Given $N \times M$ matrix $A$, a size $N$ vector $b$. Please calculate a (size $M$) vector $x$ s.t. $Ax = b$. We consider everything $\mathbb{F}_{2}$. + +For the input and output of matrices and vectors, please treat each row as a string concatenated with its components ($0$ or $1$). +@{lang.ja} + +$N \times M$ 行列 $A$, 長さ $N$ のベクトル $b$ が与えられます。$Ax = b$ を満たす(長さ $M$ の)ベクトル $x$ を求めてください。ただし全ての要素は $\mathbb{F}_{2}$ で考えることとします。 + +行列・ベクトルの入出力の際は,各行を成分($0$ または $1$)を結合した文字列として扱ってください. +@{lang.end} + +## @{keyword.constraints} + +- $1 \leq N \leq @{param.N_MAX}$ +- $1 \leq M \leq @{param.M_MAX}$ +- $A_{ij} \in \lbrace 0,1\rbrace$ +- $b_{i} \in \lbrace 0,1\rbrace$ + +## @{keyword.input} + +``` +$N$ $M$ +$A_{0,0}A_{0,1}\cdots A_{0,M-1}$ +$A_{1,0}A_{1,1}\cdots A_{1,M-1}$ +$\vdots$ +$A_{N-1,0}A_{N-1,1}\cdots A_{N-1,M-1}$ +$b_0b_1\cdots b_{N-1}$ +``` + +## @{keyword.output} + +@{lang.en} +If there is no solution, print +@{lang.ja} +解が存在しない場合 +@{lang.end} + +``` +-1 +``` + +@{lang.en} +and if exists, print as follows. +@{lang.ja} +と出力してください.存在する場合, +@{lang.end} + + +``` +$R$ +$c_0c_1\cdots c_{M-1}$ +$d_{0,0}d_{0,1}\cdots d_{0,M-1}$ +$\vdots$ +$d_{R-1,0}d_{R-1,1}\cdots d_{R-1,M-1}$ +``` + +@{lang.en} +We note that $R$ is the rank of solution. $c_i$ is one of the solution. For each $j$, $d_{j,0}\cdots d_{j,M-1}$ is the basis of solution. +@{lang.ja} +と出力してください.ただし,$R$ は解空間の次元,$c_i$ は解のうち $1$ つとし,各 $j$ について,$d_{j,0}\cdots d_{j,M-1}$ は解空間の基底ベクトルとします. +@{lang.end} + +## @{keyword.sample} + +@{example.example_00} + +@{example.example_01} + +@{example.example_02} diff --git a/linear_algebra/system_of_linear_equations_mod_2/verifier.cpp b/linear_algebra/system_of_linear_equations_mod_2/verifier.cpp new file mode 100644 index 00000000..d2afe488 --- /dev/null +++ b/linear_algebra/system_of_linear_equations_mod_2/verifier.cpp @@ -0,0 +1,26 @@ +#include +#include +#include "params.h" +#include "testlib.h" + +using namespace std; + +int main() { + registerValidation(); + int n = inf.readInt(1, N_MAX); + inf.readSpace(); + int m = inf.readInt(1, M_MAX); + inf.readChar('\n'); + for (int i = 0; i < n; i++) { + string S = inf.readToken(); + inf.readChar('\n'); + ensure(int(S.size()) == m); + for (auto& ch: S) { ensure(ch == '0' || ch == '1'); } + } + string S = inf.readToken(); + inf.readChar('\n'); + ensure(int(S.size()) == n); + for (auto& ch: S) { ensure(ch == '0' || ch == '1'); } + inf.readEof(); + return 0; +}