Skip to content

Commit

Permalink
Merge pull request #1201 from Misuki743/master
Browse files Browse the repository at this point in the history
add problem: unionfind with potential (non-commutative group)
  • Loading branch information
NachiaVivias authored Jul 18, 2024
2 parents f59a877 + ed0cb9a commit 8650ac6
Show file tree
Hide file tree
Showing 12 changed files with 1,315 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// 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");
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
4 10
0 1 0 2 998244350 998244350 5
1 0 2
0 2 1 1 2 3 7
0 2 0 998244346 998244336 12 29
0 0 2 1 2 1 3
0 3 1 2 0 0 499122177
1 0 2
1 2 0
1 3 0
1 1 1
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
#include <array>
#include <iostream>
#include "random.h"
#include "../sol/acl.h"
#include "../params.h"

using namespace std;
using namespace atcoder;

using mint = modint998244353;
using matrix = array<array<mint, 2>, 2>;

matrix id() {
matrix M;
M[0][0] = M[1][1] = 1, M[0][1] = M[1][0] = 0;
return M;
}

matrix op(const matrix &A, const matrix &B) {
matrix C;
for(int i : {0, 1})
for(int k : {0, 1})
for(int j : {0, 1})
C[i][j] += A[i][k] * B[k][j];
return C;
}

matrix inv(const matrix &A) {
matrix M = A;
swap(M[0][0], M[1][1]);
M[0][1] *= -1, M[1][0] *= -1;
return M;
}

int main(int, char* argv[]) {

long long seed = atoll(argv[1]);
auto gen = Random(seed);

auto random_matrix = [&gen]() {
matrix M;
while(M[0][0] * M[1][1] - M[0][1] * M[1][0] != 1) {
for(int i : {0, 1}) for(int j : {0, 1})
M[i][j] = gen.uniform(0ll, MOD - 1);
int k = gen.uniform(0, 3);
if (k == 0 and M[1][1] != 0)
M[0][0] = (M[0][1] * M[1][0] + 1) / M[1][1];
if (k == 1 and M[1][0] != 0)
M[0][1] = (M[0][0] * M[1][1] - 1) / M[1][0];
if (k == 2 and M[0][1] != 0)
M[1][0] = (M[0][0] * M[1][1] - 1) / M[0][1];
if (k == 3 and M[0][0] != 0)
M[1][1] = (M[0][1] * M[1][0] + 1) / M[0][0];
}

return M;
};

int n = gen.uniform<int>(1, N_MAX);
int q = Q_MAX;

vector<matrix> A(n);
for(int i = 0; i < n; i++)
A[i] = random_matrix();

printf("%d %d\n", n, q);
for (int i = 0; i < q; i++) {
int ty = gen.uniform_bool();
int a = gen.uniform(0, n - 1);
int b = gen.uniform(0, n - 1);
if (ty == 1) {
printf("%d %d %d\n", ty, a, b);
} else {
matrix M;
if (gen.uniform_bool())
M = random_matrix();
else
M = op(inv(A[b]), A[a]);
printf("%d %d %d %d %d %d %d\n", ty, a, b, M[0][0].val(), M[0][1].val(), M[1][0].val(), M[1][1].val());
}
}
return 0;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
#include "random.h"
#include "../params.h"
#include "../sol/acl.h"
#include <array>
#include <cassert>
#include <cstdio>
#include <cstdlib>
#include <numeric>
#include <utility>
#include <vector>
#include <algorithm>

using namespace std;
using namespace atcoder;

using mint = modint998244353;
using matrix = array<array<mint, 2>, 2>;

matrix id() {
matrix M;
M[0][0] = M[1][1] = 1, M[0][1] = M[1][0] = 0;
return M;
}

matrix op(const matrix &A, const matrix &B) {
matrix C;
for(int i : {0, 1})
for(int k : {0, 1})
for(int j : {0, 1})
C[i][j] += A[i][k] * B[k][j];
return C;
}

matrix inv(const matrix &A) {
matrix M = A;
swap(M[0][0], M[1][1]);
M[0][1] *= -1, M[1][0] *= -1;
return M;
}

int main(int, char *argv[]) {
const long long seed = std::atoll(argv[1]);
Random gen(seed);

const int N_AND_Q = std::min(N_MAX, Q_MAX);

struct query_type {
int t;
int u;
int v;
};

std::vector<query_type> qs(N_AND_Q);

// unused-but-set-variable が誤反応するようなので、抑制する
#if defined(__GNUC__) && !defined(__llvm__) && !defined(__INTEL_COMPILER)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
#endif
if (seed == 0 || seed == 1) {
// parent[v] = u 最悪ケース
const int K = 2 * N_AND_Q / 3;
for (int i = 0; i != K; i += 1) {
auto &[t, u, v] = qs[i];
t = 0;
u = i + 1;
v = 0;
}
for (int i = K; i != N_AND_Q; i += 1) {
auto &[t, u, v] = qs[i];
t = 1;
u = 0;
v = 1;
}
}
if (seed == 2 || seed == 3) {
// parent[v] = u 深さ最大
for (int i = 0; i != N_AND_Q - 1; i += 1) {
auto &[t, u, v] = qs[i];
t = 0;
u = i + 1;
v = i;
}
{
auto &[t, u, v] = qs[N_AND_Q - 1];
t = 0;
u = 0;
v = N_AND_Q - 1;
}
}
if (seed == 1 || seed == 3) {
// u, v 反転
for (auto &query : qs) {
std::swap(query.u, query.v);
}
}
#if defined(__GNUC__) && !defined(__llvm__) && !defined(__INTEL_COMPILER)
#pragma GCC diagnostic pop
#endif

auto random_matrix = [&gen]() {
matrix M;
while(M[0][0] * M[1][1] - M[0][1] * M[1][0] != 1) {
for(int i : {0, 1}) for(int j : {0, 1})
M[i][j] = gen.uniform(0ll, MOD - 1);
int k = gen.uniform(0, 3);
if (k == 0 and M[1][1] != 0)
M[0][0] = (M[0][1] * M[1][0] + 1) / M[1][1];
if (k == 1 and M[1][0] != 0)
M[0][1] = (M[0][0] * M[1][1] - 1) / M[1][0];
if (k == 2 and M[0][1] != 0)
M[1][0] = (M[0][0] * M[1][1] - 1) / M[0][1];
if (k == 3 and M[0][0] != 0)
M[1][1] = (M[0][1] * M[1][0] + 1) / M[0][0];
}

return M;
};

vector<matrix> A(N_AND_Q);
for(int i = 0; i < N_AND_Q; i++)
A[i] = random_matrix();

std::vector<int> p(N_AND_Q);
std::iota(p.begin(), p.end(), 0);
gen.shuffle(p.begin(), p.end());
std::printf("%d %d\n", N_AND_Q, N_AND_Q);
for (const auto &[t, u, v] : qs) {
if (t == 1) {
std::printf("%d %d %d\n", t, p[u], p[v]);
} else {
matrix M;
if (gen.uniform_bool())
M = random_matrix();
else
M = op(inv(A[v]), A[u]);
std::printf("%d %d %d %d %d %d %d\n", t, p[u], p[v], M[0][0].val(), M[0][1].val(), M[1][0].val(), M[1][1].val());
}
}

return 0;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
#include <array>
#include <iostream>
#include "random.h"
#include "../sol/acl.h"
#include "../params.h"

using namespace std;
using namespace atcoder;

using mint = modint998244353;
using matrix = array<array<mint, 2>, 2>;

matrix id() {
matrix M;
M[0][0] = M[1][1] = 1, M[0][1] = M[1][0] = 0;
return M;
}

matrix op(const matrix &A, const matrix &B) {
matrix C;
for(int i : {0, 1})
for(int k : {0, 1})
for(int j : {0, 1})
C[i][j] += A[i][k] * B[k][j];
return C;
}

matrix inv(const matrix &A) {
matrix M = A;
swap(M[0][0], M[1][1]);
M[0][1] *= -1, M[1][0] *= -1;
return M;
}

int main(int, char* argv[]) {

long long seed = atoll(argv[1]);
auto gen = Random(seed);

auto random_matrix = [&gen]() {
matrix M;
while(M[0][0] * M[1][1] - M[0][1] * M[1][0] != 1) {
for(int i : {0, 1}) for(int j : {0, 1})
M[i][j] = gen.uniform(0ll, MOD - 1);
int k = gen.uniform(0, 3);
if (k == 0 and M[1][1] != 0)
M[0][0] = (M[0][1] * M[1][0] + 1) / M[1][1];
if (k == 1 and M[1][0] != 0)
M[0][1] = (M[0][0] * M[1][1] - 1) / M[1][0];
if (k == 2 and M[0][1] != 0)
M[1][0] = (M[0][0] * M[1][1] - 1) / M[0][1];
if (k == 3 and M[0][0] != 0)
M[1][1] = (M[0][1] * M[1][0] + 1) / M[0][0];
}

return M;
};

int n = gen.uniform<int>(1, N_MAX);
int q = gen.uniform<int>(1, Q_MAX);

vector<matrix> A(n);
for(int i = 0; i < n; i++)
A[i] = random_matrix();

printf("%d %d\n", n, q);
for (int i = 0; i < q; i++) {
int ty = gen.uniform_bool();
int a = gen.uniform(0, n - 1);
int b = gen.uniform(0, n - 1);
if (ty == 1) {
printf("%d %d %d\n", ty, a, b);
} else {
matrix M;
if (gen.uniform_bool())
M = random_matrix();
else
M = op(inv(A[b]), A[a]);
printf("%d %d %d %d %d %d %d\n", ty, a, b, M[0][0].val(), M[0][1].val(), M[1][0].val(), M[1][1].val());
}
}
return 0;
}
Loading

0 comments on commit 8650ac6

Please sign in to comment.