Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

テストケース追加(Issue 1017) #1042

Closed
wants to merge 18 commits into from
29 changes: 29 additions & 0 deletions math/gcd_of_gaussian_integers/checker.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#include <vector>
#include <utility>
#include <stdint.h>
#include <inttypes.h>
#include "testlib.h"

using namespace std;

int main(int argc, char* argv[]) {
setName("compare sequences of tokens");
registerTestlibCmd(argc, argv);

int T = inf.readInt();

for (int t = 0; t < T; ++t) {
int ouf_a = ouf.readInt();
int ouf_b = ouf.readInt();
int ans_a = ans.readInt();
int ans_b = ans.readInt();
bool ok = 0;
for (int i = 0; i < 4; ++i) {
tie(ans_a, ans_b) = make_pair(ans_b, -ans_a);
if (ouf_a == ans_a && ouf_b == ans_b) ok = 1;
}
if (!ok) { quitf(_wa, "wa, gcd is not correct"); }
}
quitf(_ok, "OK");
return 0;
}
69 changes: 69 additions & 0 deletions math/gcd_of_gaussian_integers/gaussian.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#include <tuple>

template <typename T, typename U>
T floor(T x, U y) {
return (x > 0 ? x / y : (x - y + 1) / y);
}

template <typename T>
struct Gaussian_Integer {
T x, y;
using G = Gaussian_Integer;

Gaussian_Integer(T x = 0, T y = 0) : x(x), y(y) {}
Gaussian_Integer(pair<T, T> p) : x(p.fi), y(p.se) {}

T norm() const { return x * x + y * y; }
G conjugate() const { return G(x, -y); }

G &operator+=(const G &g) {
x += g.x, y += g.y;
return *this;
}
G &operator-=(const G &g) {
x -= g.x, y -= g.y;
return *this;
}
G &operator*=(const G &g) {
tie(x, y) = make_pair(x * g.x - y * g.y, x * g.y + y * g.x);
return *this;
}
G &operator/=(const G &g) {
*this *= g.conjugate();
T n = g.norm();
x = floor(x + n / 2, n);
y = floor(y + n / 2, n);
return *this;
}
G &operator%=(const G &g) {
auto q = G(*this) / g;
q *= g;
(*this) -= q;
return *this;
}
G operator-() { return G(-x, -y); }
G operator+(const G &g) { return G(*this) += g; }
G operator-(const G &g) { return G(*this) -= g; }
G operator*(const G &g) { return G(*this) *= g; }
G operator/(const G &g) { return G(*this) /= g; }
G operator%(const G &g) { return G(*this) %= g; }
bool operator==(const G &g) { return (x == g.x && y == g.y); }

static G gcd(G a, G b) {
while (b.x != 0 || b.y != 0) {
a %= b;
swap(a, b);
}
return a;
}

// (g,x,y) s.t ax+by=g
static tuple<G, G, G> extgcd(G a, G b) {
if (b.x != 0 || b.y != 0) {
G q = a / b;
auto [g, x, y] = extgcd(b, a - q * b);
return {g, y, x - q * y};
}
return {a, G{1, 0}, G{0, 0}};
}
};
9 changes: 9 additions & 0 deletions math/gcd_of_gaussian_integers/gen/example_00.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
8
8 0 6 0
0 0 0 0
0 0 4 8
4 0 6 2
1 2 3 4
1 -2 3 4
1 -3 5 -7
-344235 225420 -33882 162741
30 changes: 30 additions & 0 deletions math/gcd_of_gaussian_integers/gen/fibonacci_like.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#include <iostream>
#include <vector>
#include <tuple>

#include "../params.h"
#include "random.h"

using namespace std;
using ll = long long;

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

int T = T_MAX;
printf("%d\n", T);
for (int t = 0; t < T; ++t) {
ll a = 1, b = 0, c = 0, d = 0;
while (1) {
int k = gen.uniform<int>(0, 3);
for (int i = 0; i < k; ++i) { tie(a, b) = make_pair(b, -a); }
ll aa = c + a, bb = d + b, cc = a, dd = b;
if (min<ll>({aa, bb, cc, dd}) < MIN) break;
if (max<ll>({aa, bb, cc, dd}) > MAX) break;
a = aa, b = bb, c = cc, d = dd;
}
printf("%lld %lld %lld %lld\n", a, b, c, d);
}
return 0;
}
38 changes: 38 additions & 0 deletions math/gcd_of_gaussian_integers/gen/large_gcd.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#include <iostream>
#include <vector>
#include <tuple>

#include "../params.h"
#include "random.h"

using namespace std;
using ll = long long;

#include "../gaussian.hpp"

using G = Gaussian_Integer<ll>;

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

ll LIM1 = 1000;
ll LIM2 = 1000000 / 2;

auto gen_gauss = [&](ll LIM) -> G {
ll x = gen.uniform<int>(-LIM, LIM);
ll y = gen.uniform<int>(-LIM, LIM);
return G{x, y};
};

int T = T_MAX;
printf("%d\n", T);
for (int t = 0; t < T; ++t) {
G g = gen_gauss(LIM2);
G a = gen_gauss(LIM1);
G b = gen_gauss(LIM1);
a *= g, b *= g;
printf("%lld %lld %lld %lld\n", a.x, a.y, b.x, b.y);
}
return 0;
}
24 changes: 24 additions & 0 deletions math/gcd_of_gaussian_integers/gen/random.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#include <iostream>
#include <vector>
#include <tuple>

#include "../params.h"
#include "random.h"

using namespace std;

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

int T = T_MAX;
printf("%d\n", T);
for (int t = 0; t < T; ++t) {
int a = gen.uniform<int>(MIN, MAX);
int b = gen.uniform<int>(MIN, MAX);
int c = gen.uniform<int>(MIN, MAX);
int d = gen.uniform<int>(MIN, MAX);
printf("%d %d %d %d\n", a, b, c, d);
}
return 0;
}
32 changes: 32 additions & 0 deletions math/gcd_of_gaussian_integers/gen/small.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#include <iostream>
#include <vector>
#include <tuple>

#include "../params.h"
#include "random.h"

using namespace std;

int main(int, char* argv[]) {
long long seed = atoll(argv[1]);
// auto gen = Random(seed); つかわない

const int LIM = 10;
vector<tuple<int, int, int, int>> problems;
for (int a = -LIM; a <= LIM; ++a) {
for (int b = -LIM; b <= LIM; ++b) {
for (int c = -LIM; c <= LIM; ++c) {
for (int d = -LIM; d <= LIM; ++d) {
if ((a + b + c + d + seed) % 2 == 0)
problems.emplace_back(a, b, c, d);
}
}
}
}

int t = problems.size();
assert(1 <= t && t <= T_MAX);
printf("%d\n", t);
for (auto& [a, b, c, d]: problems) { printf("%d %d %d %d\n", a, b, c, d); }
return 0;
}
26 changes: 26 additions & 0 deletions math/gcd_of_gaussian_integers/hash.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"example_00.in": "7dc4086ba8bec80ef0442494f94ecc4a3c75c95a254541287dc5cf510505e798",
"example_00.out": "92d60e96fca7f75cecea6765a1f5c6ef19ad8dbdcf8bd143bc68e532d136dde3",
"fibonacci_like_00.in": "ef21064f421a0b2a0315a720191616108a9e0ae88c6497f9dd731236ace1c772",
"fibonacci_like_00.out": "902c656dda476a0a456e7dd4caf007959b880058822049d404db3d8c6ab5d154",
"fibonacci_like_01.in": "c59c734522884d8cf794590b4ed3e3242d0cb6a0eaab2ad5ef106fc0a9d46cf2",
"fibonacci_like_01.out": "628b2d4bf31bd31c1ef8c7742d82d3605f2e28986ed2760e7f5c5e1277f8245b",
"large_gcd_00.in": "d9478f45c4f0190fc3cd3542eb6b1532511435940b5f145568479ab489a98085",
"large_gcd_00.out": "98db471072ba552e365fd63092889aa3db929b72071eabd6a903e5149ad657f7",
"large_gcd_01.in": "14ac6874495297c0018908bdedf7091f99e86321959d7e3bc31930e2b36d9fb8",
"large_gcd_01.out": "2d6dcdbfe2b7ed410e86d8d5bf3938db4dc85bda29ac9f9b2587233b71093b59",
"random_00.in": "6e05b9b9b6b78ab540355def3a15b5b66e46d4eac200f862b76b978e5ca13120",
"random_00.out": "e20fac6eb4c1896334f2b27b4872e3d4ae54160eda5f43b4820d0b0b5d657ccb",
"random_01.in": "dfc10c33c94add6e5634143aecd6e6bf9af5e75980d8d4241a46f2ca005e3415",
"random_01.out": "0d529841ac84c6f6ccebd368f51e31153ebdbe7c5508220f47d309e94744a5ac",
"random_02.in": "a041c3e17d097ebe215e9fd21e92904780812384aafd862f358251b656aa021b",
"random_02.out": "8435c8d791ac6ac2c119d794acecbb744b0fcb96dd6d230f5af352d3fd083099",
"random_03.in": "28eb47c73ecd35f46a5f9fb4b93d225fba69e0f17950eb13db5c6f716abcf0d1",
"random_03.out": "e0f22148a4831745357cded508e63b54883166e52ae5dc73c39fe30a9e5890ad",
"random_04.in": "b6077663099db878634f78b06e4ac5e113057e4e2ed4b8292bc6c2f868952f86",
"random_04.out": "902772158b1abb1aaee812016737848b4f932eb9b5a98f99c534f21f343e5444",
"small_00.in": "3cbe5b6a235266af934850e3d27399a6e9ee4785dbe017f9a8be49bb72d4a52d",
"small_00.out": "62f870f657880fbffa49257dc28ff258fa553744cc6fed47a05ad3463d7af4da",
"small_01.in": "fa819ca05c040e2e8861bb418dfdfa2af2846b5d6d548daf57e03a7a7723b66b",
"small_01.out": "4b1063c4c397b40d8a6733bfd2a232ea128b54605059285c7bc34733711e5b5e"
}
32 changes: 32 additions & 0 deletions math/gcd_of_gaussian_integers/info.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
title = 'Gcd of Gaussian Integers'
timelimit = 5.0
forum = "https://github.com/yosupo06/library-checker-problems/issues/958"

[[tests]]
name = "example.in"
number = 1

[[tests]]
name = "small.cpp"
number = 2

[[tests]]
name = "random.cpp"
number = 5

[[tests]]
name = "fibonacci_like.cpp"
number = 2

[[tests]]
name = "large_gcd.cpp"
number = 2

[[solutions]]
name = "random_correct.cpp"
wrong = false

[params]
T_MAX = 100000
MIN = -1000000000
MAX = 1000000000
29 changes: 29 additions & 0 deletions math/gcd_of_gaussian_integers/sol/correct.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#include <cstdio>
#include <vector>
#include <cassert>

using namespace std;
using ll = long long;

#include "../gaussian.hpp"

using G = Gaussian_Integer<ll>;

int main() {
int T;
scanf("%d", &T);

for (int t = 0; t < T; ++t) {
ll a1, b1, a2, b2;
scanf("%lld %lld %lld %lld", &a1, &b1, &a2, &b2);
G a(a1, b1);
G b(a2, b2);
auto [g, x, y] = G::extgcd(a, b);
assert(a * x + b * y == g);
assert((g == G{0, 0} && a == G{0, 0}) || (a % g == 0));
assert((g == G{0, 0} && b == G{0, 0}) || (b % g == 0));
printf("%lld %lld\n", g.x, g.y);
}

return 0;
}
32 changes: 32 additions & 0 deletions math/gcd_of_gaussian_integers/sol/random_correct.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#include <cstdio>
#include <vector>
#include <cassert>

using namespace std;
using ll = long long;

#include "../gaussian.hpp"

using G = Gaussian_Integer<ll>;

int main() {
int T;
scanf("%d", &T);

G I{0, 1};

for (int t = 0; t < T; ++t) {
ll a1, b1, a2, b2;
scanf("%lld %lld %lld %lld", &a1, &b1, &a2, &b2);
G a(a1, b1);
G b(a2, b2);
auto [g, x, y] = G::extgcd(a, b);
assert(a * x + b * y == g);
assert((g == G{0, 0} && a == G{0, 0}) || (a % g == 0));
assert((g == G{0, 0} && b == G{0, 0}) || (b % g == 0));
for (int i = 0; i < t % 4; ++i) { g *= I; }
printf("%lld %lld\n", g.x, g.y);
}

return 0;
}
Loading