QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#796010 | #9804. Guess the Polygon | ucup-team4435# | RE | 8ms | 3744kb | C++20 | 42.6kb | 2024-12-01 06:10:38 | 2024-12-01 06:10:39 |
Judging History
answer
#line 1 "/home/andyli/OneDrive/lixiang/code/r.cpp"
#pragma GCC optimize("-Ofast")
// #define CHECK_EOF
// #define LX_DEBUG
#line 2 "/home/andyli/lib/all.hpp"
#if defined(LX_LOCAL) && !defined(CPH)
#include <timer.hpp>
#endif
#line 2 "/home/andyli/lib/types.hpp"
#include <bits/stdc++.h>
using u8 = unsigned char;
using u16 = unsigned short;
using u32 = unsigned int;
using u64 = unsigned long long;
using u128 = unsigned __int128;
using usize = std::uintptr_t;
using isize = std::intptr_t;
using i8 = signed char;
using i16 = short;
using i32 = int;
using i64 = long long;
using i128 = __int128;
using f64 = double;
using ld = long double;
#define vc std::vector
template <typename T>
using vvc = vc<vc<T>>;
template <typename T>
using vvvc = vc<vvc<T>>;
using vi = vc<int>;
using vvi = vc<vi>;
using vvvi = vc<vvi>;
using pi = std::pair<int, int>;
using str = std::string;
template <typename T>
using PQ = std::priority_queue<T>;
template <typename T>
using PQG = std::priority_queue<T, vc<T>, std::greater<>>;
template <typename T>
struct make_unsigned: public std::make_unsigned<T> {};
template <>
struct make_unsigned<i128> {
using type = u128;
};
template <typename T>
using make_unsigned_t = make_unsigned<T>::type;
template <typename T>
struct make_signed: public std::make_signed<T> {};
template <>
struct make_signed<u128> {
using type = i128;
};
template <typename T>
using make_signed_t = make_signed<T>::type;
template <typename T>
concept tupleLike = requires { typename std::tuple_element_t<0, std::decay_t<T>>; } && !requires (T t) { t[0]; };
template <typename T>
concept Signed = std::signed_integral<T> || std::is_same_v<T, i128>;
template <typename T>
concept Unsigned = std::unsigned_integral<T> || std::is_same_v<T, u128>;
template <typename T>
concept Integer = Signed<T> || Unsigned<T>;
template <typename T>
concept Modint = requires { T::mod(); };
template <typename T>
concept StaticModint = requires { typename std::integral_constant<decltype(T::mod()), T::mod()>; };
#line 3 "/home/andyli/lib/template.hpp"
using namespace std::ranges;
using namespace std::literals;
// NOLINTBEGIN
#define FOR1(a) for (std::decay_t<decltype(a)> _ = 0; _ < (a); _++)
#define FOR2(i, a) for (std::decay_t<decltype(a)> i = 0; i < (a); i++)
#define FOR3(i, a, b) for (auto i = (a); i < (b); i++)
#define FOR4(i, a, b, c) for (auto i = (a); i < (b); i += (c))
#define FOR1_R(a) FOR2_R(i, a)
#define FOR2_R(i, a) for (auto i = (a); i--;)
#define FOR3_R(i, a, b) for (auto i = (b); i-- > (a);)
#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 foreach(x, a) for (auto&& x: a)
#define loop while (true)
[[maybe_unused]] struct {
constexpr auto operator->*(auto&& f) const { return f(); }
} blk;
#define BLK blk->*[&]
#define lowbit(x) ((x) & (-(x)))
#define all(x) begin(x), end(x)
#define rall(x) rbegin(x), rend(x)
#define LB(c, x) distance(begin(c), lower_bound(c, x))
#define UB(c, x) distance(begin(c), upper_bound(c, x))
#define UNIQUE(c) sort(c), (c).erase(std::unique(all(c)), end(c))
#define VEC(type, a, ...) auto a = vec<type>(__VA_ARGS__)
#define VECI(a, ...) auto a = veci(__VA_ARGS__)
#define FORWARD(x) std::forward<decltype(x)>(x)
#define eb emplace_back
#if defined(LX_LOCAL) || defined(ASSERTIONS)
#define ASSERT(...) assert(__VA_ARGS__)
#else
#define ASSERT(...) void()
#endif
// NOLINTEND
constexpr auto floor(auto&& x, auto&& y) { return x / y - (x % y && (x ^ y) < 0); }
constexpr auto ceil(auto&& x, auto&& y) { return floor(x + y - 1, y); }
constexpr auto divmod(auto x, auto y) {
auto&& q = floor(x, y);
return std::pair{q, x - q * y};
}
constexpr u64 ten(int t) { return t == 0 ? 1 : ten(t - 1) * 10; }
constexpr int get_lg(auto n) { return n <= 1 ? 1 : std::__bit_width(n - 1); }
constexpr auto Max(const auto& x) { return x; }
constexpr auto Min(const auto& x) { return x; }
constexpr auto Max(const auto& x, const auto& y, const auto&... arg) { return x < y ? Max(y, arg...) : Max(x, arg...); }
constexpr auto Min(const auto& x, const auto& y, const auto&... arg) { return x < y ? Min(x, arg...) : Min(y, arg...); }
constexpr bool chkmax(auto& d, const auto&... x) {
auto t = Max(x...);
return t > d ? d = t, true : false;
}
constexpr bool chkmin(auto& d, const auto&... x) {
auto t = Min(x...);
return t < d ? d = t, true : false;
}
constexpr auto sum(input_range auto&& r) { return std::accumulate(all(r), range_value_t<decltype(r)>{}); }
constexpr auto sum(input_range auto&& r, auto init) { return std::accumulate(all(r), init); }
constexpr int len(auto&& x) { return size(x); }
template <typename T>
auto cumsum(const vc<T>& a) {
int n = len(a);
vc<T> b(n + 1);
_for (i, n)
b[i + 1] = b[i] + a[i];
return b;
}
template <typename T>
auto cumsum(auto&& a) {
int n = len(a);
vc<T> b(n + 1);
_for (i, n)
b[i + 1] = b[i] + a[i];
return b;
}
template <typename T>
auto vec(usize n, auto&&... s) {
if constexpr (!sizeof...(s))
return vc<T>(n);
else
return vc(n, vec<T>(s...));
}
auto veci(usize n, auto&&... s) {
if constexpr (sizeof...(s) == 1)
return vc(n, s...);
else
return vc(n, veci(s...));
}
template <typename T>
vi argsort(const vc<T>& a) {
vi p(len(a));
iota(all(p), 0);
sort(p, [&](int i, int j) { return std::pair{a[i], i} < std::pair{a[j], j}; });
return p;
}
vi sshift(const str& s, char c = 'a') {
vi a(len(s));
_for (i, len(s))
a[i] = s[i] - c;
return a;
}
template <typename T>
T pop(vc<T>& q) {
T r = std::move(q.back());
q.pop_back();
return r;
}
template <typename T>
T pop(std::deque<T>& q) {
T r = std::move(q.front());
q.pop_front();
return r;
}
template <typename T, typename S, typename C>
T pop(std::priority_queue<T, S, C>& q) {
T r = q.top();
q.pop();
return r;
}
template <typename T>
constexpr T inf = std::numeric_limits<T>::max() * 0.49;
template <>
constexpr f64 inf<f64> = inf<i64>;
template <>
constexpr ld inf<ld> = inf<i64>;
#line 3 "/home/andyli/lib/utility/itos_table.hpp"
constexpr auto itos_table = [] {
std::array<u32, 10000> O{};
int x = 0;
_for (i, 10)
_for (j, 10)
_for (k, 10)
_for (l, 10)
O[x++] = i + j * 0x100 + k * 0x10000 + l * 0x1000000 + 0x30303030;
return O;
}();
#line 3 "/home/andyli/lib/io.hpp"
#define FASTIO
#ifdef CHECK_EOF
#define ECHK0 *ip ? *ip++ : 0
#define ECHK1 \
if (ch == EV) \
return set(false), *this;
#define ECHK2 \
if (!*ip) \
return set(false), *this;
#define ECHK3 &&ch != -1
#define ECHK4 &&*ip
#define ECHK5 \
if (ch == -1) \
return set(false);
#define ECHK6 \
if (!*ip) \
return set(false);
#else
#define ECHK0 *ip++
#define ECHK1
#define ECHK2
#define ECHK3
#define ECHK4
#define ECHK5
#define ECHK6
#endif
#if defined(__unix__) && !defined(LX_DEBUG) && !defined(LX_LOCAL)
#define USE_MMAP
#define EV 0
#include <sys/mman.h>
#include <sys/stat.h>
#else
#define EV (-1)
#endif
struct IO {
static constexpr usize bufSize = 1 << 20;
static constexpr bool isdigit(int c) { return '0' <= c && c <= '9'; }
static constexpr bool blank(int c) { return c <= ' '; }
u32 prec = 12;
FILE *in, *out;
bool status;
#ifndef LX_DEBUG
char obuf[bufSize], *ip, *op = obuf;
#ifndef USE_MMAP
char ibuf[bufSize], *eip;
#endif
#endif
#ifdef LX_DEBUG
int getch() { return fgetc(in); }
int getch_unchecked() { return getch(); }
int unget(int c = -1) { return ungetc(c, in); }
int peek() { return unget(getch()); }
void input(FILE* f) { in = f, set(); }
void skipws() {
int ch = getch();
while (blank(ch) ECHK3)
ch = getch();
unget(ch);
}
void ireadstr(char* s, usize n) { fread(s, 1, n, in); }
#elif defined(USE_MMAP)
void skipws() {
while (blank(*ip) ECHK4)
ip++;
ECHK6
}
int unget(int = 0) = delete;
int getch() { return ECHK0; }
int getch_unchecked() { return *ip++; }
int peek() { return *ip; }
void input(FILE* f) {
struct stat st;
int fd;
in = f;
if (in)
fd = fileno(in), fstat(fd, &st), ip = (char*)mmap(nullptr, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0), set();
}
void ireadstr(char* s, usize n) { memcpy(s, ip, n), ip += n; }
static constexpr auto I = [] {
std::array<u32, 0x10000> I{};
fill(I, -1);
_for (i, 10)
_for (j, 10)
I[i + j * 0x100 + 0x3030] = i * 10 + j;
return I;
}();
#else
void skipws() {
int ch = getch();
while (blank(ch) ECHK3)
ch = getch();
ECHK5
unget();
}
int unget(int = 0) { return *ip--; }
int getch() { return (ip == eip ? (eip = (ip = ibuf) + fread(ibuf, 1, bufSize, in)) : nullptr), ip == eip ? -1 : *ip++; }
int getch_unchecked() { return *ip++; }
int peek() { return (ip == eip ? (eip = (ip = ibuf) + fread(ibuf, 1, bufSize, in)) : nullptr), ip == eip ? -1 : *ip; }
void input(FILE* f) { in = f, ip = eip = ibuf, set(); }
void ireadstr(char* s, usize n) {
if (usize len = eip - ip; n > len) [[unlikely]] {
memcpy(s, ip, len);
n -= len;
s += len;
ip = eip;
fread(s, 1, n, in);
}
else
memcpy(s, ip, n), ip += n;
}
#endif
void input(std::string_view s) { input(fopen(s.data(), "rb")); }
void set(bool s = true) { status = s; }
IO(FILE* i = stdin, FILE* o = stdout) { input(i), output(o); }
~IO() { flush(); }
template <typename... Args>
requires (sizeof...(Args) > 1)
IO& read(Args&... x) {
#ifdef CHECK_EOF
(read(x) && ...);
#else
(read(x), ...);
#endif
return *this;
}
template <Signed T>
IO& read(T& x) {
x = 0;
make_unsigned_t<T> t;
bool sign = false;
#ifndef USE_MMAP
int ch = getch();
while (!isdigit(ch) ECHK3)
sign = ch == '-', ch = getch();
ECHK1
t = 0;
while (isdigit(ch))
t = t * 10 + (ch ^ 48), ch = getch();
unget(ch);
#else
while (!isdigit(*ip) ECHK4)
sign = *ip++ == '-';
ECHK2
t = *ip++ ^ 48;
u16* tip = (u16*)ip;
while (~I[*tip])
t = t * 100 + I[*tip++];
ip = (char*)tip;
if (isdigit(*ip))
t = t * 10 + (*ip++ ^ 48);
#endif
x = sign ? -t : t;
return *this;
}
IO& read(Unsigned auto& x) {
x = 0;
#ifndef USE_MMAP
int ch = getch();
while (!isdigit(ch) ECHK3)
ch = getch();
ECHK1
while (isdigit(ch))
x = x * 10 + (ch ^ 48), ch = getch();
unget(ch);
#else
while (!isdigit(*ip) ECHK4)
ip++;
ECHK2
x = *ip++ ^ 48;
u16* tip = (u16*)ip;
while (~I[*tip])
x = x * 100 + I[*tip++];
ip = (char*)tip;
if (isdigit(*ip))
x = x * 10 + (*ip++ ^ 48);
#endif
return *this;
}
IO& read(std::floating_point auto& x) {
static str s;
if (read(s))
std::from_chars(s.begin().base(), s.end().base(), x);
return *this;
}
template <typename T = int>
T read() {
std::decay_t<T> x;
return read(x), x;
}
IO& read(char& ch) {
skipws();
ch = getch();
ECHK1
return *this;
}
#ifdef USE_MMAP
usize next_size() const {
char* ip = this->ip;
while (!blank(*ip) ECHK4)
ip++;
return ip - this->ip;
}
IO& read(char* s) {
skipws();
auto n = next_size();
ireadstr(s, n);
s[n] = 0;
return *this;
}
IO& read(str& s) {
skipws();
auto n = next_size();
s.assign(ip, n);
ip += n;
return *this;
}
IO& readstr(str& s, usize n) {
skipws();
s.assign(ip, n);
ip += n;
return *this;
}
#else
IO& read(char* s) {
skipws();
int ch = peek();
ECHK1
while (!blank(ch))
*s++ = ch, getch_unchecked(), ch = peek();
*s = 0;
return *this;
}
IO& read(str& s) {
skipws();
int ch = peek();
ECHK1
s.erase();
while (!blank(ch))
s.append(1, ch), getch_unchecked(), ch = peek();
return *this;
}
IO& readstr(str& s, usize n) {
skipws();
s.resize(n);
ireadstr(s.data(), n);
return *this;
}
#endif
IO& readstr(char* s, usize n) {
skipws();
ireadstr(s, n);
s[n] = 0;
return *this;
}
IO& readline(char* s) {
char* t = s;
int ch = getch();
while (ch != '\n' && ch != EV)
*s++ = ch, ch = getch();
*s = 0;
if (s == t && ch == EV)
set(false);
return *this;
}
IO& readline(str& s) {
s.erase();
int ch = getch();
while (ch != '\n' && ch != EV)
s.append(1, ch), ch = getch();
if (s.empty() && ch == EV)
set(false);
return *this;
}
IO& read(tupleLike auto& t) {
return std::apply([&](auto&... t) { (read(t), ...); }, t), *this;
}
IO& read(forward_range auto&& r) { return readArray(FORWARD(r)); }
template <typename T>
requires requires (T t, IO& io) { t.read(io); }
IO& read(T& t) { return t.read(*this), *this; }
template <std::forward_iterator I>
IO& readArray(I f, I l) {
while (f != l)
read(*f++);
return *this;
}
IO& readArray(forward_range auto&& r) { return readArray(all(r)); }
IO& zipread(auto&&... a) {
_for (i, (len(a), ...))
read(a[i]...);
return *this;
}
#ifdef LX_DEBUG
void flush() { fflush(out), set(); }
void putch_unchecked(char c) { fputc(c, out); }
void putch(char c) { putch_unchecked(c); }
void writestr(const char* s, usize n) { fwrite(s, 1, n, out); }
#else
void flush() { fwrite(obuf, 1, op - obuf, out), op = obuf; }
void putch_unchecked(char c) { *op++ = c; }
void putch(char c) { (op == end(obuf) ? flush() : void()), putch_unchecked(c); }
void writestr(const char* s, usize n) {
if (n >= usize(end(obuf) - op)) [[unlikely]]
flush(), fwrite(s, 1, n, out);
else
memcpy(op, s, n), op += n;
}
#endif
void output(std::string_view s) { output(fopen(s.data(), "wb")); }
void output(FILE* f) { out = f; }
void setprec(u32 n = 6) { prec = n; }
template <typename... Args>
requires (sizeof...(Args) > 1)
void write(Args&&... x) { (write(FORWARD(x)), ...); }
void write() const {}
template <Signed T>
void write(T x) {
make_unsigned_t<T> y = x;
if (x < 0)
putch('-'), write(y = -y);
else
write(y);
}
void write(std::unsigned_integral auto x) {
#ifndef LX_DEBUG
if (end(obuf) - op < 64) [[unlikely]]
flush();
auto L = [&](int x) { return x == 1 ? 0 : ten(x - 1); };
auto R = [&](int x) { return ten(x) - 1; };
auto&& O = itos_table;
#define de(t) \
case L(t)... R(t): \
*(u32*)op = O[x / ten((t) - 4)]; \
op += 4; \
x %= ten((t) - 4); \
[[fallthrough]]
switch (u64(x)) {
de(18);
de(14);
de(10);
de(6);
case L(2)... R(2):
*(u32*)op = O[x * 100];
op += 2;
break;
de(17);
de(13);
de(9);
de(5);
case L(1)... R(1):
*op++ = x ^ 48;
break;
default:
*(u32*)op = O[x / ten(16)];
op += 4;
x %= ten(16);
[[fallthrough]];
de(16);
de(12);
de(8);
case L(4)... R(4):
*(u32*)op = O[x];
op += 4;
break;
de(19);
de(15);
de(11);
de(7);
case L(3)... R(3):
*(u32*)op = O[x * 10];
op += 3;
break;
}
#undef de
#else
write(u128(x));
#endif
}
void write(u128 x) {
#ifndef LX_DEBUG
if (end(obuf) - op < 64) [[unlikely]]
flush();
#endif
static int s[40], t = 0;
do
s[t++] = x % 10, x /= 10;
while (x);
while (t)
putch_unchecked(s[--t] ^ 48);
}
void write(char c) { putch(c); }
void write(std::floating_point auto x) {
static char buf[512];
writestr(buf, std::to_chars(buf, buf + 512, x, std::chars_format::fixed, prec).ptr - buf);
}
void write(std::string_view s) { writestr(s.data(), s.size()); }
template <typename I, typename T = std::iter_value_t<I>>
static constexpr char default_delim = tupleLike<T> || (input_range<T> && !requires (range_value_t<T> x) { {x} -> std::same_as<char&>; }) ? '\n' : ' ';
template <std::input_iterator I, std::sentinel_for<I> S>
void print_range(I f, S l, char d = default_delim<I>) {
if (f != l)
for (write(*f++); f != l; write(*f++))
putch(d);
}
template <tupleLike T>
void write(T&& t) {
[&]<auto... I>(std::index_sequence<I...>) {
(..., (!I ? void() : putch(' '), write(std::get<I>(t))));
}(std::make_index_sequence<std::tuple_size_v<std::decay_t<T>>>());
}
template <input_range R>
requires (!std::same_as<range_value_t<R>, char>)
void write(R&& r) { print_range(all(r)); }
template <typename T>
requires requires (T t, IO& io) { t.write(io); }
void write(T&& t) { t.write(*this); }
void writeln(auto&&... x) { write(FORWARD(x)...), print(); }
void print() { putch('\n'); }
void print(auto&& x, auto&&... y) {
write(FORWARD(x));
((putch(' '), write(FORWARD(y))), ...);
print();
}
template <std::input_iterator I, std::sentinel_for<I> S>
void displayArray(I f, S l, char d = default_delim<I>) { print_range(f, l, d), print(); }
template <input_range R>
void displayArray(R&& r, char d = default_delim<iterator_t<R>>) { displayArray(all(r), d); }
operator bool() const { return status; }
} io;
#ifdef LX_LOCAL
IO err(nullptr, stderr);
#define dbg(x) err.print(#x, '=', x)
#else
#define dbg(x) \
do { \
} while (false)
#endif
#define dR(type, ...) \
type __VA_ARGS__; \
io.read(__VA_ARGS__)
#define dRV(type, a, ...) \
VEC(type, a, __VA_ARGS__); \
io.read(a)
#define STR(s, n) \
str s; \
io.readstr(s, n)
void multipleTests(auto&& f) {
dR(u32, q);
_for (q)
f();
}
void writeln(auto&&... x) { io.writeln(FORWARD(x)...); }
void print(auto&&... x) { io.print(FORWARD(x)...); }
void YES(bool v = true) { io.write(v ? "YES\n" : "NO\n"); }
inline void NO(bool v = true) { YES(!v); }
void Yes(bool v = true) { io.write(v ? "Yes\n" : "No\n"); }
inline void No(bool v = true) { Yes(!v); }
#line 5 "/home/andyli/OneDrive/lixiang/code/r.cpp"
#line 3 "/home/andyli/lib/poly/fft.hpp"
namespace CFFT {
template <typename T>
struct Cp {
T x{}, y{};
Cp operator+(const Cp& c) const { return {x + c.x, y + c.y}; }
Cp& operator+=(const Cp& c) { return *this = *this + c; }
Cp operator-(const Cp& c) const { return {x - c.x, y - c.y}; }
Cp& operator-=(const Cp& c) { return *this = *this - c; }
Cp operator*(const Cp& c) const { return {x * c.x - y * c.y, x * c.y + y * c.x}; }
Cp operator*=(const Cp& c) { return *this = *this * c; }
Cp operator*(T z) const { return {x * z, y * z}; }
Cp operator*=(T z) { return *this = *this * z; }
Cp operator-() const { return {-x, -y}; }
Cp conj() const { return {x, -y}; }
Cp rotl() const { return {-y, x}; }
};
using C = Cp<f64>;
vc<C> w;
void setw(int k) {
if (len(w) >= (1 << --k))
return;
w.resize(1 << k);
w[0] = {1, 0};
for (int i = 1; i < (1 << k); i <<= 1) {
auto arg = std::numbers::pi / (i << 1);
w[i] = {cos(arg), sin(arg)};
}
_for (i, 1, 1 << k)
w[i] = w[i & (i - 1)] * w[lowbit(i)];
}
void fft(vc<C>& a, int k) {
if (len(a) <= 1)
return;
if (k == 1) {
a[0] += std::exchange(a[1], a[0] - a[1]);
return;
}
if (k & 1) {
int v = 1 << (k - 1);
_for (j, v)
a[j] += std::exchange(a[j + v], a[j] - a[j + v]);
}
int u = 1 << (k & 1), v = 1 << (k - 2 - (k & 1));
C imag = w[1];
while (v) {
for (int j0 = 0, j1 = v, j2 = j1 + v, j3 = j2 + v; j0 < v; j0++, j1++, j2++, j3++) {
C t0 = a[j0], t1 = a[j1], t2 = a[j2], t3 = a[j3];
C t0p2 = t0 + t2, t1p3 = t1 + t3;
C t0m2 = t0 - t2, t1m3 = (t1 - t3) * imag;
a[j0] = t0p2 + t1p3, a[j1] = t0p2 - t1p3;
a[j2] = t0m2 + t1m3, a[j3] = t0m2 - t1m3;
}
_for (jh, 1, u) {
C ww = w[jh], xx = w[jh << 1], wx = ww * xx;
for (int j0 = (jh * v) << 2, j1 = j0 + v, j2 = j1 + v, j3 = j2 + v, je = j1; j0 < je; j0++, j1++, j2++, j3++) {
C t0 = a[j0], t1 = a[j1] * xx, t2 = a[j2] * ww, t3 = a[j3] * wx;
C t0p2 = t0 + t2, t1p3 = t1 + t3;
C t0m2 = t0 - t2, t1m3 = (t1 - t3) * w[1];
a[j0] = t0p2 + t1p3, a[j1] = t0p2 - t1p3;
a[j2] = t0m2 + t1m3, a[j3] = t0m2 - t1m3;
}
}
u <<= 2, v >>= 2;
}
}
void ifft(vc<C>& a, int k) {
if (len(a) <= 1)
return;
if (k == 1) {
a[0] += std::exchange(a[1], a[0] - a[1]);
return;
}
int u = 1 << (k - 2), v = 1;
C imag = w[1].conj();
while (u) {
for (int j0 = 0, j1 = v, j2 = j1 + v, j3 = j2 + v; j0 < v; j0++, j1++, j2++, j3++) {
C t0 = a[j0], t1 = a[j1], t2 = a[j2], t3 = a[j3];
C t0p1 = t0 + t1, t2p3 = t2 + t3;
C t0m1 = t0 - t1, t2m3 = (t2 - t3) * imag;
a[j0] = t0p1 + t2p3, a[j2] = t0p1 - t2p3;
a[j1] = t0m1 + t2m3, a[j3] = t0m1 - t2m3;
}
_for (jh, 1, u) {
C ww = w[jh].conj(), xx = w[jh << 1].conj(), yy = w[(jh << 1) + 1].conj();
for (int j0 = (jh * v) << 2, j1 = j0 + v, j2 = j1 + v, j3 = j2 + v, je = j1; j0 < je; j0++, j1++, j2++, j3++) {
C t0 = a[j0], t1 = a[j1], t2 = a[j2], t3 = a[j3];
C t0p1 = t0 + t1, t2p3 = t2 + t3;
C t0m1 = (t0 - t1) * xx, t2m3 = (t2 - t3) * yy;
a[j0] = t0p1 + t2p3, a[j2] = (t0p1 - t2p3) * ww;
a[j1] = t0m1 + t2m3, a[j3] = (t0m1 - t2m3) * ww;
}
}
u >>= 2, v <<= 2;
}
if (k & 1) {
u = 1 << (k - 1);
_for (j, u)
a[j] += std::exchange(a[j + u], a[j] - a[j + u]);
}
}
} // namespace CFFT
#line 3 "/home/andyli/lib/poly/convolution_naive.hpp"
template <typename T, typename U = T>
vc<U> convolution_naive(const vc<T>& a, const vc<T>& b) {
int n = len(a), m = len(b);
if (n > m)
return convolution_naive<T, U>(b, a);
if (!n)
return {};
vc<U> r(n + m - 1);
_for (i, n)
_for (j, m)
r[i + j] += U(a[i]) * b[j];
return r;
}
#line 8 "/home/andyli/OneDrive/lixiang/code/r.cpp"
// 0: neg = false, dat = {}
struct bigint {
using M = bigint;
static constexpr int logD = 7;
static constexpr u32 D = 10000000, B = 1 << 14;
bool neg = false;
vi dat;
bigint() = default;
bigint(bool n, vi d): neg(n), dat(std::move(d)) {}
template <Signed T>
bigint(T x) {
make_unsigned_t<T> y = x;
if (x < 0)
neg = true, y = -y;
dat = _from_int(y);
}
template <Unsigned T>
bigint(T x): dat(_from_int(x)) {}
bigint(std::string_view s) {
if (s == "0")
return;
if (s[0] == '-')
s = s.substr(1), neg = true;
for (int ie = len(s); 0 < ie; ie -= logD) {
int is = max(0, ie - logD);
int x = 0;
_for (i, is, ie) {
x = x * 10 + (s[i] >= 'A' ? s[i] - 'A' + 10 : s[i] - '0');
}
dat.eb(x);
}
}
void ok_write() const {
using namespace std;
if (dat.empty()) {
cout << "0";
return;
}
if (neg)
cout << "-";
for (int i = dat.size(); i--;) {
cout << _itos(dat[i], i != dat.size() - 1);
}
}
#ifdef FASTIO
void read(IO& io) {
static str s;
io.read(s);
*this = bigint(s);
}
void write(IO& io) const {
if (dat.empty()) {
io.putch('0');
return;
}
if (neg)
io.putch('-');
_for_r (i, len(dat))
io.write(_itos(dat[i], i != len(dat) - 1));
}
#endif
friend M operator+(const M& lhs, const M& rhs) {
if (lhs.neg == rhs.neg)
return {lhs.neg, _add(lhs.dat, rhs.dat)};
if (_leq(lhs.dat, rhs.dat)) {
auto c = _sub(rhs.dat, lhs.dat);
bool n = rhs.neg && !c.empty();
return {n, std::move(c)};
}
auto c = _sub(lhs.dat, rhs.dat);
bool n = lhs.neg && !c.empty();
return {n, std::move(c)};
}
friend M operator-(const M& lhs, const M& rhs) {
if (rhs.dat.empty())
return lhs;
if (lhs.neg == !rhs.neg)
return {lhs.neg, _add(lhs.dat, rhs.dat)};
if (_leq(lhs.dat, rhs.dat)) {
auto c = _sub(rhs.dat, lhs.dat);
bool n = !rhs.neg && !c.empty();
return {n, std::move(c)};
}
auto c = _sub(lhs.dat, rhs.dat);
bool n = lhs.neg && !c.empty();
return {n, std::move(c)};
}
friend M operator*(const M& lhs, const M& rhs) {
auto c = _mul(lhs.dat, rhs.dat);
bool n = (lhs.neg ^ rhs.neg) && !c.empty();
return {n, std::move(c)};
}
friend auto divmod(const M& lhs, const M& rhs) {
auto dm = _divmod_newton(lhs.dat, rhs.dat);
bool dn = lhs.neg != rhs.neg && !dm.first.empty();
bool mn = lhs.neg && !dm.second.empty();
return std::pair{M{dn, std::move(dm.first)}, M{mn, std::move(dm.second)}};
}
friend M operator/(const M& lhs, const M& rhs) { return divmod(lhs, rhs).first; }
friend M operator%(const M& lhs, const M& rhs) { return divmod(lhs, rhs).second; }
M& operator+=(const M& rhs) { return *this = *this + rhs; }
M& operator-=(const M& rhs) { return *this = *this - rhs; }
M& operator*=(const M& rhs) { return *this = *this * rhs; }
M& operator/=(const M& rhs) { return *this = *this / rhs; }
M& operator%=(const M& rhs) { return *this = *this % rhs; }
M& operator++() { return *this += 1; }
M operator++(int) {
M t = *this;
++*this;
return t;
}
M& operator--() { return *this -= 1; }
M operator--(int) {
M t = *this;
--*this;
return t;
}
M operator-() const {
if (dat.empty())
return *this;
return {!neg, dat};
}
M operator+() const { return *this; }
friend M abs(const M& m) { return {false, m.dat}; }
friend bool operator==(const M& lhs, const M& rhs) = default;
friend bool operator<(const M& lhs, const M& rhs) { return lhs != rhs && _neq_lt(lhs, rhs); }
friend bool operator<=(const M& lhs, const M& rhs) { return !(rhs < lhs); }
friend bool operator>(const M& lhs, const M& rhs) { return rhs < lhs; }
friend bool operator>=(const M& lhs, const M& rhs) { return !(lhs < rhs); }
template <typename T>
T to_int() const {
T r = _to_int<T>(dat);
return neg ? -r : r;
}
private:
static bool _lt(const vi& a, const vi& b) {
if (len(a) != len(b))
return len(a) < len(b);
_for_r (i, len(a))
if (a[i] != b[i])
return a[i] < b[i];
return false;
}
static bool _leq(const vi& a, const vi& b) { return a == b || _lt(a, b); }
static bool _neq_lt(const M& lhs, const M& rhs) {
if (lhs.neg != rhs.neg)
return lhs.neg;
return _lt(lhs.dat, rhs.dat) ^ lhs.neg;
}
static bool _is_one(const vi& a) { return len(a) == 1 && a[0] == 1; }
static void _shrink(vi& a) {
while (!a.empty() && !a.back())
a.pop_back();
}
static vi _add(const vi& a, const vi& b) {
vi c(max(len(a), len(b)) + 1);
_for (i, max(len(a), len(b))) {
if (i < len(a))
c[i] += a[i];
if (i < len(b))
c[i] += b[i];
if (c[i] >= D)
c[i] -= D, c[i + 1]++;
}
_shrink(c);
return c;
}
static vi _sub(vi a, const vi& b) {
int t = 0;
_for (i, len(a)) {
if (i < len(b))
t += b[i];
a[i] -= t;
t = 0;
if (a[i] < 0)
a[i] += D, t = 1;
}
_shrink(a);
return a;
}
static vi _mul_naive(const vi& a, const vi& b) {
auto c = convolution_naive<int, u64>(a, b);
vi r(len(a) + len(b) + 2);
u64 x = 0;
_for (i, len(c)) {
x += c[i];
r[i] = x % D, x /= D;
}
int i = len(c);
while (x)
r[i++] = x % D, x /= D;
_shrink(r);
return r;
}
static vi _mul(const vi& a, const vi& b) {
using namespace CFFT;
if (a.empty() || b.empty())
return {};
if (_is_one(a))
return b;
if (_is_one(b))
return a;
int n = len(a), m = len(b);
if (min(n, m) <= 30)
return _mul_naive(a, b);
int k = get_lg(n + m), sz = 1 << k;
vc<C> c(sz), d(sz);
_for (i, n)
c[i] = {f64(a[i] % B), f64(a[i] / B)};
_for (i, m)
d[i] = {f64(b[i] % B), f64(b[i] / B)};
setw(k);
fft(c, k), fft(d, k);
f64 fx = 1.0 / sz, fy = fx * 0.25;
c[0] = {c[0].x * d[0].x + c[0].y * d[0].y, c[0].x * d[0].y + c[0].y * d[0].x};
c[0] *= fx;
c[1] *= d[1] * fx;
for (int k = 2, m = 3; k < sz; k <<= 1, m <<= 1)
for (int i = k, j = i + k - 1; i < m; i++, j--) {
C oi = c[i] + c[j].conj(), hi = c[i] - c[j].conj();
C oj = d[i] + d[j].conj(), hj = d[i] - d[j].conj();
C r0 = oi * oj - hi * hj * ((i & 1) ? -w[i >> 1] : w[i >> 1]);
C r1 = oj * hi + oi * hj;
c[i] = (r0 + r1) * fy;
c[j] = (r0 - r1).conj() * fy;
}
ifft(c, k);
vi r(n + m + 2);
u64 x = 0;
_for (i, n + m) {
x += i64(c[i].x + 0.5) + i64(c[i].y + 0.5) * B;
r[i] = x % D, x /= D;
}
int i = n + m;
while (x)
r[i++] = x % D, x /= D;
_shrink(r);
return r;
}
static auto _divmod_li(const vi& a, const vi& b) {
i64 va = _to_int<i64>(a), vb = b[0];
return std::pair{_from_int(va / vb), _from_int(va % vb)};
}
static auto _divmod_i64(const vi& a, const vi& b) {
i64 va = _to_int<i64>(a), vb = _to_int<i64>(b);
return std::pair{_from_int(va / vb), _from_int(va % vb)};
}
static auto _divmod_1e8(const vi& a, const vi& b) {
if (b[0] == 1)
return std::pair{a, vi{}};
if (len(a) <= 2)
return _divmod_li(a, b);
vi quo(len(a));
i64 d = 0;
int b0 = b[0];
_for_r (i, len(a)) {
d = d * D + a[i];
int q = d / b0, r = d % b0;
quo[i] = q, d = r;
}
_shrink(quo);
return std::pair{std::move(quo), d ? vi{int(d)} : vi{}};
}
static auto _divmod_naive(const vi& a, const vi& b) {
ASSERT(!b.empty());
if (len(b) == 1)
return _divmod_1e8(a, b);
if (max(len(a), len(b)) <= 2)
return _divmod_i64(a, b);
if (_lt(a, b))
return std::pair{vi{}, a};
int norm = D / (b.back() + 1);
vi x = _mul(a, {norm});
vi y = _mul(b, {norm});
int yb = y.back();
vi quo(len(x) - len(y) + 1);
vi rem(x.end() - len(y), x.end());
_for_r (i, len(quo)) {
if (len(rem) == len(y)) {
if (_leq(y, rem))
quo[i] = 1, rem = _sub(rem, y);
}
else if (len(rem) > len(y)) {
i64 rb = i64(rem[len(rem) - 1]) * D + rem[len(rem) - 2];
int q = rb / yb;
vi yq = _mul(y, {q});
while (_lt(rem, yq))
q--, yq = _sub(yq, y);
rem = _sub(rem, yq);
while (_leq(y, rem))
q++, rem = _sub(rem, y);
quo[i] = q;
}
if (i)
rem.insert(rem.begin(), x[i - 1]);
}
_shrink(quo), _shrink(rem);
auto [q2, r2] = _divmod_1e8(rem, {norm});
return std::pair{std::move(quo), std::move(q2)};
}
static vi _calc_inv(const vi& a, int deg) {
int k = deg, c = len(a);
while (k > 64)
k = (k + 1) >> 1;
vi z(c + k + 1);
z.back() = 1;
z = _divmod_naive(z, a).first;
while (k < deg) {
vi s = _mul(z, z);
s.insert(s.begin(), 0);
int d = min(c, 2 * k + 1);
vi t(a.end() - d, a.end()), u = _mul(s, t);
u.erase(u.begin(), u.begin() + d);
vi w(k + 1), w2 = _add(z, z);
w.insert(w.end(), all(w2));
z = _sub(w, u);
z.erase(z.begin());
k <<= 1;
}
z.erase(z.begin(), z.begin() + k - deg);
return z;
}
static std::pair<vi, vi> _divmod_newton(const vi& a, const vi& b) {
ASSERT(!b.empty());
if (len(b) <= 64 || len(a) - len(b) <= 64)
return _divmod_naive(a, b);
int norm = D / (b.back() + 1);
vi x = _mul(a, {norm}), y = _mul(b, {norm});
int s = len(x), t = len(y);
int deg = s - t + 2;
vi z = _calc_inv(y, deg);
vi q = _mul(x, z);
q.erase(q.begin(), q.begin() + t + deg);
vi yq = _mul(y, {q});
while (_lt(x, yq))
q = _sub(q, {1}), yq = _sub(yq, y);
vi r = _sub(x, yq);
while (_leq(y, r))
q = _add(q, {1}), r = _sub(r, y);
_shrink(q), _shrink(r);
auto [q2, r2] = _divmod_1e8(r, {norm});
return {std::move(q), std::move(q2)};
}
static str _itos(int x, bool zero_padding) {
str r;
_for (i, logD) {
int t = x % 10;
r += char(t < 10 ? '0' + t : 'A' + t - 10);
x /= 10;
}
if (!zero_padding)
while (!r.empty() && r.back() == '0')
r.pop_back();
reverse(r);
return r;
}
static vi _from_int(Integer auto x) {
vi r;
while (x)
r.eb(x % D), x /= D;
return r;
}
template <typename T>
static T _to_int(const vi& a) {
T r{};
_for_r (i, len(a))
r = r * D + a[i];
return r;
}
};
bigint gcd(const bigint &a, const bigint &b) {
if (b == bigint(0)) {
return a;
}
return gcd(b, a % b);
}
template<class T>
class Frac {
public:
T num;
T den;
void normalize() {
bigint g = gcd(num, den);
if (g < bigint(0)) {
g = bigint(0) - g;
}
num /= g;
den /= g;
}
Frac &operator+=(const Frac &rhs) {
num = num * rhs.den + rhs.num * den;
den *= rhs.den;
return *this;
}
Frac &operator-=(const Frac &rhs) {
num = num * rhs.den - rhs.num * den;
den *= rhs.den;
return *this;
}
Frac &operator*=(const Frac &rhs) {
num *= rhs.num;
den *= rhs.den;
return *this;
}
Frac &operator/=(const Frac &rhs) {
num *= rhs.den;
den *= rhs.num;
if (den < bigint(0)) {
num = bigint(0) - num;
den = bigint(0) - den;
}
return *this;
}
friend Frac operator+(Frac lhs, const Frac &rhs) {
return lhs += rhs;
}
friend Frac operator-(Frac lhs, const Frac &rhs) {
return lhs -= rhs;
}
friend Frac operator*(Frac lhs, const Frac &rhs) {
return lhs *= rhs;
}
friend Frac operator/(Frac lhs, const Frac &rhs) {
return lhs /= rhs;
}
friend Frac operator-(const Frac &a) {
return Frac(bigint(0) - a.num, a.den);
}
friend bool operator==(const Frac &lhs, const Frac &rhs) {
return lhs.num * rhs.den == rhs.num * lhs.den;
}
friend bool operator!=(const Frac &lhs, const Frac &rhs) {
return lhs.num * rhs.den != rhs.num * lhs.den;
}
friend bool operator<(const Frac &lhs, const Frac &rhs) {
return lhs.num * rhs.den < rhs.num * lhs.den;
}
friend bool operator>(const Frac &lhs, const Frac &rhs) {
return lhs.num * rhs.den > rhs.num * lhs.den;
}
friend bool operator<=(const Frac &lhs, const Frac &rhs) {
return lhs.num * rhs.den <= rhs.num * lhs.den;
}
friend bool operator>=(const Frac &lhs, const Frac &rhs) {
return lhs.num * rhs.den >= rhs.num * lhs.den;
}
};
using Fraction = Frac<bigint>;
Fraction ask(bigint p, bigint q) {
q *= 4;
using namespace std;
cout << "? ";
p.ok_write();
cout << ' ';
q.ok_write();
cout << endl;
string r, s;
cin >> r >> s;
return {bigint(r), bigint(s)};
// bigint r, s; cin >> r >> s;
// return {r, s};
// dR(bigint, a, b);
// return {a, b};
}
void solve() {
using namespace std;
using ll = long long;
map<int, int> cnt;
int n; cin >> n;
// dR(int, n);
for (int _ = 0; _ < n; _++) {
// dR(int, x, y);
int x, y;
cin >> x >> y;
x *= 4;
cnt[x]++;
}
vector<pair<ll, ll>> a(cnt.begin(), cnt.end());
if (a.size() <= 1) {
cout << "! 0 1" << endl;
// print("! 0 1");
// io.flush();
return;
}
Fraction result = {bigint(0), bigint(1)};
vector<Fraction> to_sum;
auto Add = [&] (Fraction len1, Fraction len2, Fraction xdiff, Fraction ladd, Fraction radd) {
// assert(xdiff.num != bigint(0));
Fraction L = len1;
Fraction R = len2;
if (ladd == radd) {
} else if (ladd.num != bigint(0)) {
auto df = len1 - len2;
df /= xdiff;
df *= (xdiff + ladd);
L = df + len2;
} else if (radd.num != bigint(0)) {
auto df = len2 - len1;
df /= xdiff;
df *= (xdiff + radd);
R = df + len1;
} else {
assert(0);
}
auto h = xdiff + ladd + radd;
auto res = (L + R) * h;
to_sum.push_back(res);
};
Fraction len1, ladd, prv;
if (a[0].second == 1) {
len1 = {bigint(0), bigint(1)};
ladd = {bigint(0), bigint(1)};
prv = {bigint(a[0].first), bigint(1)};
} else {
len1 = ask(bigint(a[0].first), bigint(1));
ladd = {bigint(0), bigint(1)};
prv = {bigint(a[0].first), bigint(1)};
}
for(int i = 1; i + 1 < (int)a.size(); ++i) {
if (a[i].second == 1) {
Fraction nx = {bigint(a[i].first), bigint(1)};
Fraction cur = ask(bigint(a[i].first), bigint(1));
Add(len1, cur, nx - prv, ladd, Fraction{bigint(0), bigint(1)});
prv = nx;
ladd = {bigint(0), bigint(1)};
len1 = cur;
continue;
}
Fraction radd = {bigint(1), bigint(1)};
Fraction nx = {bigint(a[i].first), bigint(1)};
Fraction rp = nx - radd;
Fraction len2 = ask(rp.num, rp.den);
Fraction xdiff = rp - prv;
Add(len1, len2, xdiff, ladd, radd);
prv = nx + radd;
ladd = radd;
len1 = ask(prv.num, prv.den);
}
{
Fraction radd = {bigint(0), bigint(1)};
Fraction nx = {a.back().first, 1};
Fraction len2 = {bigint(0), bigint(1)};
if (a.back().second > bigint(1)) {
len2 = ask(nx.num, nx.den);
}
Add(len1, len2, nx - prv, ladd, radd);
}
auto rec = [&](auto &&self, int l, int r) -> Fraction {
if (r - l == 1) {
return to_sum[l];
}
int mid = (l + r) / 2;
return self(self, l, mid) + self(self, mid, r);
};
result = rec(rec, 0, to_sum.size());
result.den *= bigint(8);
result.normalize();
cout << "! ";
result.num.ok_write();
cout << ' ';
result.den.ok_write();
cout << endl;
// cout << "! " << result.num << ' ' << result.den << endl;
// print("!", result.num, result.den);
// io.flush();
}
int main() {
using namespace std;
cin.tie(nullptr)->sync_with_stdio(false);
int t;
cin >> t;
while (t--) {
solve();
}
// multipleTests([&] {
// solve();
// });
return 0;
}
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 100
Accepted
time: 0ms
memory: 3728kb
input:
2 4 3 0 1 3 1 1 0 0 3 2 7 4 3 0 0 999 1000 1000 999 1999 1000
output:
? 3 4 ? 5 4 ! 3 1 ? 3996 4 ! 1999 2
result:
ok correct! (2 test cases)
Test #2:
score: 0
Accepted
time: 1ms
memory: 3684kb
input:
9 4 1 1 1 3 3 0 0 0 9 4 7 8 4 0 0 1 3 1 1 3 0 3 4 21 8 4 0 0 3 0 1 2 1 1 3 4 7 8 4 0 0 3 0 1 2 1 1 3 2 7 8 4 0 0 3 0 1 1 1 2 3 4 7 4 3 1000 0 0 0 0 1000 1000 1 4 0 0 1000 0 1000 1000 0 1000 1000 1 1000 1 5 0 1 1000 1000 1000 0 0 1000 1 0 999 1 1000 1 1000 1 9 4 1000 3 1 2 1000 3 1000 1 1 2 1 0 0 1 1...
output:
? 3 4 ? 5 4 ! 5 2 ? 3 4 ? 5 4 ! 7 2 ? 3 4 ? 5 4 ! 3 2 ? 3 4 ? 5 4 ! 2 1 ? 3 4 ? 5 4 ! 5 2 ? 0 4 ! 500000 1 ? 0 4 ? 4000 4 ! 1000000 1 ? 0 4 ? 4 4 ? 4000 4 ! 1999999 2 ? 3 4 ? 5 4 ? 7 4 ? 9 4 ? 11 4 ? 13 4 ? 16 4 ! 4003 2
result:
ok correct! (9 test cases)
Test #3:
score: 0
Accepted
time: 8ms
memory: 3744kb
input:
78 8 951 614 927 614 957 614 957 604 937 614 942 619 951 610 927 604 10 1 10 1 15 1 25 4 10 1 10 1 7 562 260 602 250 582 255 587 260 602 260 562 250 577 260 10 1 10 1 5 1 10 1 10 1 3 454 98 494 68 455 68 117 4 3 526 589 566 559 527 559 117 4 3 854 496 854 466 894 466 30 1 3 797 264 827 254 857 264 1...
output:
? 3708 4 ? 3748 4 ? 3768 4 ? 3803 4 ? 3805 4 ? 3828 4 ! 317 1 ? 2248 4 ? 2308 4 ? 2328 4 ? 2348 4 ? 2408 4 ! 375 1 ? 1820 4 ! 585 1 ? 2108 4 ! 585 1 ? 3416 4 ! 600 1 ? 3308 4 ! 300 1 ? 2876 4 ! 600 1 ? 648 4 ! 400 1 ? 2968 4 ? 2987 4 ? 2989 4 ? 3007 4 ? 3009 4 ? 3168 4 ! 275 1 ? 3728 4 ? 3747 4 ? 37...
result:
ok correct! (78 test cases)
Test #4:
score: -100
Runtime Error
input:
34 24 123 815 168 800 133 795 27 827 153 805 28 830 178 780 138 810 78 830 192 772 148 790 88 810 43 825 183 795 103 805 163 785 118 800 93 825 63 835 73 815 58 820 198 790 48 840 108 820 10 3 95 6 15 2 95 6 15 2 95 6 15 2 95 6 15 2 95 6 15 2 95 6 15 2 95 6 15 2 95 6 15 2 95 6 15 2 95 6 15 2 15 1 24...
output:
? 112 4 ? 172 4 ? 192 4 ? 232 4 ? 252 4 ? 292 4 ? 312 4 ? 352 4 ? 372 4 ? 412 4 ? 432 4 ? 472 4 ? 492 4 ? 532 4 ? 552 4 ? 592 4 ? 612 4 ? 652 4 ? 672 4 ? 712 4 ? 732 4 ? 768 4 ! 1925 1 ? 216 4 ? 276 4 ? 296 4 ? 336 4 ? 356 4 ? 396 4 ? 416 4 ? 456 4 ? 476 4 ? 516 4 ? 536 4 ? 576 4 ? 596 4 ? 636 4 ? 6...