Skip to content

Commit

Permalink
Merge pull request yosupo06#1248 from maspypy/solve_linear
Browse files Browse the repository at this point in the history
問題追加 system of linear equations (mod 2)
  • Loading branch information
maspypy authored Sep 30, 2024
2 parents e6bef87 + af20c7d commit d6fef0f
Show file tree
Hide file tree
Showing 20 changed files with 721 additions and 0 deletions.
89 changes: 89 additions & 0 deletions linear_algebra/system_of_linear_equations_mod_2/checker.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
#include <algorithm>
#include <vector>
#include <string>
#include <bitset>
#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<BS> 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<BS> 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");
}
73 changes: 73 additions & 0 deletions linear_algebra/system_of_linear_equations_mod_2/gen/base.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#include <bitset>
#include <vector>
#include "random.h"

using namespace std;
using BS = bitset<4096>;

void out(int n, int m, vector<BS> 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<BS> 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<BS> 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<int>(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<int> new_idx(n);
for (int i = 0; i < n; ++i) new_idx[i] = i;
gen.shuffle(new_idx.begin(), new_idx.end());
vector<BS> 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);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
3 3
101
011
110
011
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
3 3
101
011
110
111
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
1 3
111
1
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#include <iostream>
#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;
}
27 changes: 27 additions & 0 deletions linear_algebra/system_of_linear_equations_mod_2/gen/max_random.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#include <iostream>
#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;
}
18 changes: 18 additions & 0 deletions linear_algebra/system_of_linear_equations_mod_2/gen/max_small.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#include <iostream>
#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<int>(2, 10);
int r = gen.uniform<int>(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;
}
27 changes: 27 additions & 0 deletions linear_algebra/system_of_linear_equations_mod_2/gen/random.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#include <iostream>
#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<int>(1, N_MAX);
int m = gen.uniform<int>(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;
}
18 changes: 18 additions & 0 deletions linear_algebra/system_of_linear_equations_mod_2/gen/small_max.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#include <iostream>
#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<int>(2, 10);
int m = M_MAX;
int r = gen.uniform<int>(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;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#include <iostream>
#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<int>(1, 3);
int m = gen.uniform<int>(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;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
1 1
0
0
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
1 1
0
1
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
1 1
1
0
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
1 1
1
1
Loading

0 comments on commit d6fef0f

Please sign in to comment.