結果
| 問題 |
No.3088 XOR = SUM
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2025-04-04 22:44:07 |
| 言語 | C++17(gcc12) (gcc 12.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 462 ms / 2,000 ms |
| コード長 | 28,373 bytes |
| コンパイル時間 | 21,937 ms |
| コンパイル使用メモリ | 265,280 KB |
| 実行使用メモリ | 7,716 KB |
| 最終ジャッジ日時 | 2025-04-04 22:44:59 |
| 合計ジャッジ時間 | 42,988 ms |
|
ジャッジサーバーID (参考情報) |
judge6 / judge5 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 1 |
| other | AC * 22 |
ソースコード
//give me AC!!!!!!!!!//
#pragma GCC target("avx2")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
#include <algorithm>
#include <bitset>
#include <tuple>
#include <cstdint>
#include <cstdio>
#include <cctype>
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <cassert>
#include <cfloat>
#include <climits>
#include <cmath>
#include <complex>
#include <ctime>
#include <deque>
#include <fstream>
#include <functional>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <list>
#include <limits>
#include <map>
#include <memory>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>
#include <numeric>
#include <array>
#include <chrono>
#include <atcoder/all>
using namespace std;
using namespace atcoder;
int INF = 1e9 + 7;
long long inf = 45e17 + 11;
int mod = 998244353;
long double PI = 3.141592653589793238462643383279502884197169399375105820974944592307816406286208998626034825342117;
typedef pair<long long, long long > P;
struct mint {
int x;
mint(int x = 0) :x((x% mod + mod) % mod) {}
mint operator-() const { return mint(-x); }
mint& operator+=(const mint a) {
if ((x += a.x) >= mod) x -= mod;
return *this;
}
mint& operator-=(const mint a) {
if ((x += mod - a.x) >= mod) x -= mod;
return *this;
}
mint& operator*=(const mint a) { (x *= a.x) %= mod; return *this; }
mint operator+(const mint a) const { return mint(*this) += a; }
mint operator-(const mint a) const { return mint(*this) -= a; }
mint operator*(const mint a) const { return mint(*this) *= a; }
mint pow(int t) const {
if (!t) return 1;
mint a = pow(t >> 1);
a *= a;
if (t & 1) a *= *this;
return a;
}
mint inv() const { return pow(mod - 2); }
mint& operator/=(const mint a) { return *this *= a.inv(); }
mint operator/(const mint a) const { return mint(*this) /= a; }
};
istream& operator>>(istream& is, mint& a) { return is >> a.x; }
ostream& operator<<(ostream& os, const mint& a) { return os << a.x; }
template<class T> inline bool chmin(T& a, T b) {
if (a > b) {
a = b;
return true;
}
return false;
}
template<class T> inline bool chmax(T& a, T b) {
if (a < b) {
a = b;
return true;
}
return false;
}
long long modinv(long long a, long long m) {
long long b = m, u = 1, v = 0;
while (b) {
long long t = a / b;
a -= t * b; swap(a, b);
u -= t * v; swap(u, v);
}
u %= m;
if (u < 0) u += m;
return u;
}
bool IsPrime(int num)
{
if (num < 2) return false;
else if (num == 2) return true;
else if (num % 2 == 0) return false;
for (int i = 3; i * i <= num; i += 2)
{
if (num % i == 0)
{
return false;
}
}
return true;
}
long long gcd(long long a, long long b) {
if (b == 0)return a;
while (a % b != 0) {
long long u = a % b;
a = b;
b = u;
}
return b;
}
long long lcm(long long x, long long y) {
return x / gcd(x, y) * y;
}
const int MAX = 1000010;
const int MOD = 1000000007;
long long fac[MAX], finv[MAX], inv[MAX];
void COMinit() {
fac[0] = fac[1] = 1;
finv[0] = finv[1] = 1;
inv[1] = 1;
for (int i = 2; i < MAX; i++) {
fac[i] = fac[i - 1] * i % MOD;
inv[i] = MOD - inv[MOD % i] * (MOD / i) % MOD;
finv[i] = finv[i - 1] * inv[i] % MOD;
}
}
long long COM(int n, int k) {
if (n < k) return 0;
if (n < 0 || k < 0) return 0;
return fac[n] * (finv[k] * finv[n - k] % MOD) % MOD;
}
vector<int> sieve(int max) {
vector<bool>prime(max + 1, true);
vector<int>A;
for (int i = 2; i <= max; ++i)
if (prime[i]) {
A.push_back(i);
for (int j = 2; i * j <= max; ++j)
prime[i * j] = false;
}
return A;
}
string mmax(string S, string T) {
if (S.size() > T.size())
return S;
if (T.size() > S.size())
return T;
return max(S, T);
};
long long biggcd(vector<long long>& a) {
long long ans = 0;
for (int i = 0; i < a.size(); i++) {
ans = gcd(ans, a[i]);
}
return ans;
}
struct edge {
long long from;
long long to;
long long cost;
};
using Edges = vector<edge>;
void bfsub(const Edges& Es, int s, vector<bool>& B, vector<bool>& d, vector<bool>& f) {
B[s] = true;
for (auto e : Es) {
if (!B[e.to] && d[e.from] && d[e.to] && f[e.from] && f[e.to]) {
B[e.to] = true;
bfsub(Es, e.to, B, d, f);
}
}
}
bool bf(const Edges& Es, int V, int s, vector<long long>& dis, vector<bool>& d) {
dis.resize(V, inf);
d.resize(V, false);
int cnt = 0;
while (cnt < V) {
bool end = true;
for (auto e : Es) {
if (e.from == s && dis[e.to] == inf) {
d[e.from] = true;
dis[e.to] = e.cost;
end = false;
}
if (dis[e.from] != inf && dis[e.from] + e.cost < dis[e.to]) {
d[e.from] = true;
dis[e.to] = dis[e.from] + e.cost;
end = false;
}
}
if (end) break;
cnt++;
}
return (cnt == V);
}
template <typename T>
struct BIT {
int n; // 配列の要素数(数列の要素数+1)
vector<T> bit; // データの格納先
BIT(int n_) : n(n_ + 1), bit(n, 0) {}
// 1-index
void add(int i, T x) {
for (int idx = i; idx < n; idx += (idx & -idx)) {
bit[idx] += x;
}
}
// 1-index
T sum(int i) {
T s(0);
for (int idx = i; idx > 0; idx -= (idx & -idx)) {
s += bit[idx];
}
return s;
}
// [l,r) の区間和を取得
T query(int l, int r) { return sum(r - 1) - sum(l - 1); }
int lower_bound(T w) { // a_1 + a_2 + ... + a_x >= w となるような最小の x を求める(ただし a_i >= 0)
if (w <= 0) {
return 0;
}
else {
int x = 0, r = 1;
while (r < n) r = r << 1;
for (int len = r; len > 0; len = len >> 1) { // 長さlenは1段下るごとに半分に
if (x + len < n && bit[x + len] < w) { // 採用するとき
w -= bit[x + len];
x += len;
}
}
return x + 1;
}
}
};
// vは0以上n-1以下
int count_inversion(vector<int>& v) {
int n = v.size();
BIT<int> bit(n);
int ret = 0;
for (int i = 0; i < n; i++) {
ret += bit.query(v[i] + 1, n + 1);
bit.add(v[i] + 1, 1);
}
return ret;
}
bool bmdfs(vector<bool>& used, vector<vector<int>>& G, vector<int>& match, int v) {
used[v] = true;
for (int i = 0; i < G[v].size(); i++) {
int u = G[v][i], w = match[u];
if (w < 0 || !used[w] && bmdfs(used, G, match, w)) {
match[v] = u;
match[u] = v;
return true;
}
}
return false;
}
int bm(vector<bool>& used, vector<vector<int>>& G, vector<int>& match, int V) {
int res = 0;
for (int i = 0; i < match.size(); i++) {
match[i] = -1;
}
for (int v = 0; v < V; v++) {
if (match[v] < 0) {
for (int i = 0; i < used.size(); i++) {
used[i] = 0;
}
if (bmdfs(used, G, match, v)) {
res++;
}
}
}
return res;
}
long long sttolo(string S) {
long long count = 1000000000ll;
long long ans = 0;
for (int i = 0; i < S.size(); i++) {
if (S[i] == '.') {
count /= 10; continue;
}
if (count == 10000) {
ans *= 10;
}
ans += count * (S[i] - '0');
if (count != 1000000000ll) {
count /= 10;
}
}
return ans;
}
#define rep(i,N) for(int i=0;i<(int)(N);i++)
namespace geometry2d {
/*
for Floating Point Error
*/
constexpr double eps = 1e-10;
/*
a > 0 ... 1
a = 0 ... 0
a < 0 ... -1
*/
constexpr int sgn(const double a) {
return (a < -eps ? -1 : (a > eps ? 1 : 0));
}
struct Point {
double x, y;
Point() = default;
constexpr Point(double _x, double _y) : x(_x), y(_y) {}
double length() const { return std::sqrt(lengthSquare()); }
constexpr double lengthSquare() const noexcept(true) { return dot(*this); }
constexpr double dot(const Point& other) const noexcept(true) { return x * other.x + y * other.y; }
constexpr double cross(const Point& other) const noexcept(true) { return x * other.y - y * other.x; }
double distanceFrom(const Point& other) const noexcept(true) { return (other - *this).length(); }
Point normalized() const { return Point(x / length(), y / length()); }
constexpr bool isZero() const noexcept(true) { return x == 0.0 && y == 0.0; }
Point normalUnitVector() const { return Point(-normalized().y, normalized().x); }
Point rotation(double arg) const {
double cs = std::cos(arg), sn = std::sin(arg);
return Point(x * cs - y * sn, x * sn + y * cs);
}
double angle() const { return std::atan2(y, x); }
constexpr Point operator +() const noexcept(true) { return *this; }
constexpr Point operator -() const noexcept(true) { return Point(-x, -y); }
constexpr Point operator +(const Point& other) const noexcept(true) { return Point(x + other.x, y + other.y); }
constexpr Point operator -(const Point& other) const noexcept(true) { return Point(x - other.x, y - other.y); }
constexpr Point operator *(double s) const noexcept(true) { return Point(x * s, y * s); }
constexpr Point operator /(double s) const noexcept(true) { return Point(x / s, y / s); }
constexpr bool operator ==(const Point& other) const noexcept(true) { return sgn(x - other.x) == 0 && sgn(y - other.y) == 0; }
constexpr bool operator !=(const Point& other) const noexcept(true) { return sgn(x - other.x) || sgn(y - other.y); }
constexpr bool operator <(const Point& other) const noexcept(true) {
if (sgn(x - other.x) != 0) return sgn(x - other.x) < 0;
return sgn(y - other.y) < 0;
}
Point& operator +=(const Point& other) {
x += other.x;
y += other.y;
return *this;
}
Point& operator -=(const Point& other) {
x -= other.x;
y -= other.y;
return *this;
}
Point& operator *=(double s) {
x *= s;
y *= s;
return *this;
}
Point& operator /=(double s) {
x /= s;
y /= s;
return *this;
}
};
constexpr inline Point operator *(double a, const Point& p) { return Point(p.x * a, p.y * a); }
int angletype(const Point& a, const Point& b, const Point& c) {
double v = (a - b).dot(c - b);
return (sgn(v) > 0 ? 0 : sgn(v) < 0 ? 2 : 1);
}
struct Circle {
Point p;
double r;
Circle() = default;
constexpr Circle(Point _p, double _r) : p(_p), r(_r) {}
};
int isIntersect(const Circle& c1, const Circle& c2) {
double d = c1.p.distanceFrom(c2.p);
if (sgn(d - (c1.r + c2.r)) > 0) return 4;
if (sgn(d - (c1.r + c2.r)) == 0) return 3;
if (sgn(d - abs(c1.r - c2.r)) == 0) return 1;
if (sgn(d - abs(c1.r - c2.r)) < 0) return 0;
return 2;
}
std::vector<Point> crossPoint(const Circle& c1, const Circle& c2) {
std::vector<Point> res;
const int mode = isIntersect(c1, c2);
if (mode == 4 || mode == 0) return res;
double d = c1.p.distanceFrom(c2.p);
if (mode == 3) {
double x, y;
x = (c1.r * c2.p.x + c2.r * c1.p.x) / (c1.r + c2.r);
y = (c1.r * c2.p.y + c2.r * c1.p.y) / (c1.r + c2.r);
res.emplace_back(Point(x, y));
return res;
}
if (mode == 1) {
double x, y;
x = (-c2.r * c1.p.x + c1.r * c2.p.x) / (c1.r - c2.r);
y = (-c2.r * c1.p.y + c1.r * c2.p.y) / (c1.r - c2.r);
res.emplace_back(Point(x, y));
return res;
}
double r1cos = (c1.r * c1.r + d * d - c2.r * c2.r) / (2 * d);
double r1sin = std::sqrt(c1.r * c1.r - r1cos * r1cos);
Point vec = Point(c2.p.x - c1.p.x, c2.p.y - c1.p.y);
if (sgn(c1.r - r1cos) == 0) r1sin = 0;
Point e12 = vec.normalized();
Point h12 = vec.normalUnitVector();
res.emplace_back(c1.p + r1cos * e12 + r1sin * h12);
res.emplace_back(c1.p + r1cos * e12 - r1sin * h12);
return res;
}
}
using namespace geometry2d;
void prime_num(vector<int>& factornum) {
for (int i = 0; i < factornum.size(); i++)factornum[i] = 1;
for (int i = 2; i * i < factornum.size(); i++) {
if (factornum[i] == 1) {
for (int j = 2; i * j < factornum.size(); j++) {
factornum[i * j] = factornum[i] + factornum[j];
}
}
}
}
int dx[] = { 0,1,0,-1 }, dy[] = { 1,0,-1,0 };
struct ts_edge {
int to;
};
using graph = vector<vector<ts_edge>>;
vector<int> ts(const graph& G) {
vector<int> ans;
int n = (int)G.size();
vector<int> ind(n);
for (int i = 0; i < n; i++) {
for (auto e : G[i]) {
ind[e.to]++;
}
}
queue<int> que;
for (int i = 0; i < n; i++) {
if (ind[i] == 0) {
que.push(i);
}
}
while (!que.empty()) {
int now = que.front();
ans.push_back(now);
que.pop();
for (auto e : G[now]) {
ind[e.to]--;
if (ind[e.to] == 0) {
que.push(e.to);
}
}
}
return ans;
}
/* RMQ:[0,n-1] について、区間ごとの最小値を管理する構造体
update(a,b,x): 区間[a,b) の要素を x に更新。O(log(n))
query(a,b): [a,b) での最小の要素を取得。O(log(n))
*/
struct segment_tree {
int n;
vector<int> node;
segment_tree(int n) : n(n), node(n << 1, 0) {} // 初期値が0になりました
// i番目の要素そのものにアクセスできる機能をつけました
int operator[](int i) { return node[i + n]; }
void set(int i, int x) {
node[i += n] = x;
while (i >>= 1) node[i] = node[i << 1 | 0] + node[i << 1 | 1]; // 和になりました
}
int fold(int l, int r) {
int res = 0; // 初期値が0になりました
for (l += n, r += n; l < r; l >>= 1, r >>= 1) {
if (l & 1) res = res + node[l++]; // 和になりました
if (r & 1) res = node[--r] + res; // 和になりました
}
return res;
}
};
struct Eratosthenes {
// テーブル
vector<bool> isprime;
// 整数 i を割り切る最小の素数
vector<int> minfactor;
// コンストラクタで篩を回す
Eratosthenes(int N) : isprime(N + 1, true),
minfactor(N + 1, -1) {
// 1 は予めふるい落としておく
isprime[1] = false;
minfactor[1] = 1;
// 篩
for (int p = 2; p <= N; ++p) {
// すでに合成数であるものはスキップする
if (!isprime[p]) continue;
// p についての情報更新
minfactor[p] = p;
// p 以外の p の倍数から素数ラベルを剥奪
for (int q = p * 2; q <= N; q += p) {
// q は合成数なのでふるい落とす
isprime[q] = false;
// q は p で割り切れる旨を更新
if (minfactor[q] == -1) minfactor[q] = p;
}
}
}
// 高速素因数分解
// pair (素因子, 指数) の vector を返す
vector<pair<int, int>> factorize(int n) {
vector<pair<int, int>> res;
while (n > 1) {
int p = minfactor[n];
int exp = 0;
// n で割り切れる限り割る
while (minfactor[n] == p) {
n /= p;
++exp;
}
res.emplace_back(p, exp);
}
return res;
}
// 高速約数列挙
vector<int> divisors(int n) {
vector<int> res({ 1 });
// n を素因数分解 (メンバ関数使用)
auto pf = factorize(n);
// 約数列挙
for (auto p : pf) {
int s = (int)res.size();
for (int i = 0; i < s; ++i) {
int v = 1;
for (int j = 0; j < p.second; ++j) {
v *= p.first;
res.push_back(res[i] * v);
}
}
}
return res;
}
};
struct UnionFind {
vector<int> par, size;
UnionFind(int x) {
par.resize(x);
size.resize(x, 1);
for (int i = 0; i < x; i++) {
par[i] = i;
}
}
int find(int x) {
if (par[x] == x)
return x;
return par[x] = find(par[x]);
}
bool same(int x, int y) {
return find(x) == find(y);
}
int consize(int x) {
return size[find(x)];
}
void unite(int x, int y) {
x = find(x);
y = find(y);
if (x == y)
return;
if (size[x] < size[y]) {
par[x] = y;
size[y] += size[x];
}
else {
par[y] = x;
size[x] += size[y];
}
}
};
#define int long long
struct segment_tree_max {
int n;
vector<int> node;
segment_tree_max(int n) : n(n), node(n << 1, inf) {} // 初期値が0になりました
// i番目の要素そのものにアクセスできる機能をつけました
int operator[](int i) { return node[i + n]; }
void set(int i, int x) {
node[i += n] = x;
while (i >>= 1) node[i] = min(node[i << 1 | 0], node[i << 1 | 1]);
}
int fold(int l, int r) {
int res = inf; // 初期値が0になりました
for (l += n, r += n; l < r; l >>= 1, r >>= 1) {
if (l & 1) res = min(res, node[l++]); // 和になりました
if (r & 1) res = min(node[--r], res); // 和になりました
}
return res;
}
};
struct Edge {
long long to;
long long cost;
};
using Graph = vector<vector<Edge>>;
/* dijkstra(G,s,dis)
入力:グラフ G, 開始点 s, 距離を格納する dis
計算量:O(|E|log|V|)
副作用:dis が書き換えられる
*/
void dijkstra(const Graph& G, int s, vector<long long>& dis) {
int N = G.size();
dis.resize(N, inf);
priority_queue<P, vector<P>, greater<P>> pq; // 「仮の最短距離, 頂点」が小さい順に並ぶ
dis[s] = 0;
pq.emplace(dis[s], s);
while (!pq.empty()) {
P p = pq.top();
pq.pop();
int v = p.second;
if (dis[v] < p.first) { // 最短距離で無ければ無視
continue;
}
for (auto& e : G[v]) {
if (dis[e.to] > dis[v] + e.cost) { // 最短距離候補なら priority_queue に追加
dis[e.to] = dis[v] + e.cost;
pq.emplace(dis[e.to], e.to);
}
}
}
}
template <typename T>
struct RMQ {
const T INF = numeric_limits<T>::max();
int n;
vector<T> dat, lazy;
RMQ(int n_) : n(), dat(n_ * 4, 0), lazy(n_ * 4, 0) {
int x = 1;
while (n_ > x) x *= 2;
n = x;
}
void set(int i, T x) { dat[i + n - 1] = x; }
void build() {
for (int k = n - 2; k >= 0; k--) dat[k] = min(dat[2 * k + 1], dat[2 * k + 2]);
}
/* lazy eval */
void eval(int k) {
if (lazy[k] == 0) return; // 更新するものが無ければ終了
if (k < n - 1) { // 葉でなければ子に伝搬
lazy[k * 2 + 1] += lazy[k];
lazy[k * 2 + 2] += lazy[k];
}
// 自身を更新
dat[k] += lazy[k];
lazy[k] = 0;
}
void add(int a, int b, T x, int k, int l, int r) {
eval(k);
if (a <= l && r <= b) { // 完全に内側の時
lazy[k] += x;
eval(k);
}
else if (a < r && l < b) { // 一部区間が被る時
add(a, b, x, k * 2 + 1, l, (l + r) / 2); // 左の子
add(a, b, x, k * 2 + 2, (l + r) / 2, r); // 右の子
dat[k] = min(dat[k * 2 + 1], dat[k * 2 + 2]);
}
}
void add(int a, int b, T x) { add(a, b, x, 0, 0, n); }
T query_sub(int a, int b, int k, int l, int r) {
eval(k);
if (r <= a || b <= l) { // 完全に外側の時
return INF;
}
else if (a <= l && r <= b) { // 完全に内側の時
return dat[k];
}
else { // 一部区間が被る時
T vl = query_sub(a, b, k * 2 + 1, l, (l + r) / 2);
T vr = query_sub(a, b, k * 2 + 2, (l + r) / 2, r);
return min(vl, vr);
}
}
T query(int a, int b) { return query_sub(a, b, 0, 0, n); }
T find_rightest(int a, int b, int x) { return find_rightest_sub(a, b, x, 0, 0, n); } // 存在しなければ a-1
T find_leftest(int a, int b, int x) { return find_leftest_sub(a, b, x, 0, 0, n); } // 存在しなければ b
T find_rightest_sub(int a, int b, int x, int k, int l, int r) {
eval(k);
if (dat[k] > x || r <= a || b <= l) { // 自分の値がxより大きい or [a,b)が[l,r)の範囲外ならreturn a-1
return a - 1;
}
else if (k >= n - 1) { // 自分が葉ならその位置をreturn
return (k - (n - 1));
}
else {
int vr = find_rightest_sub(a, b, x, 2 * k + 2, (l + r) / 2, r);
if (vr != a - 1) { // 右の部分木を見て a-1 以外ならreturn
return vr;
}
else { // 左の部分木を見て値をreturn
return find_rightest_sub(a, b, x, 2 * k + 1, l, (l + r) / 2);
}
}
}
T find_leftest_sub(int a, int b, int x, int k, int l, int r) {
eval(k);
if (dat[k] > x || r <= a || b <= l) { // 自分の値がxより大きい or [a,b)が[l,r)の範囲外ならreturn b
return b;
}
else if (k >= n - 1) { // 自分が葉ならその位置をreturn
return (k - (n - 1));
}
else {
int vl = find_leftest_sub(a, b, x, 2 * k + 1, l, (l + r) / 2);
if (vl != b) { // 左の部分木を見て b 以外ならreturn
return vl;
}
else { // 右の部分木を見て値をreturn
return find_leftest_sub(a, b, x, 2 * k + 2, (l + r) / 2, r);
}
}
}
/* debug */
inline T operator[](int a) { return query(a, a + 1); }
void print() {
for (int i = 0; i < n; ++i) {
cout << (*this)[i];
if (i != n) cout << ",";
}
cout << endl;
}
};
void wf(vector<vector<long long>>& dist, vector<vector<long long>>& prev) {
int V = dist.size();
for (int k = 0; k < V; k++) {
for (int i = 0; i < V; i++) {
for (int j = 0; j < V; j++) {
if (dist[i][k] + dist[k][j] < dist[i][j]) {
dist[i][j] = dist[i][k] + dist[k][j];
prev[i][j] = prev[k][j];
}
}
}
}
}
long long power(long long x, long long n) {
long long ret = 1;
while (n > 0) {
if (n & 1) ret = ret * x % mod; // n の最下位bitが 1 ならば x^(2^i) をかける
x = x * x % mod;
n >>= 1; // n を1bit 左にずらす
}
return ret;
}
template< class T >
struct Matrix {
vector< vector< T > > A;
Matrix() {}
Matrix(size_t n, size_t m) : A(n, vector< T >(m, 0)) {}
Matrix(size_t n) : A(n, vector< T >(n, 0)) {};
size_t height() const {
return (A.size());
}
size_t width() const {
return (A[0].size());
}
inline const vector< T >& operator[](int k) const {
return (A.at(k));
}
inline vector< T >& operator[](int k) {
return (A.at(k));
}
static Matrix I(size_t n) {
Matrix mat(n);
for (int i = 0; i < n; i++) mat[i][i] = 1;
return (mat);
}
Matrix& operator+=(const Matrix& B) {
size_t n = height(), m = width();
assert(n == B.height() && m == B.width());
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++)
(*this)[i][j] += B[i][j];
return (*this);
}
Matrix& operator-=(const Matrix& B) {
size_t n = height(), m = width();
assert(n == B.height() && m == B.width());
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++)
(*this)[i][j] -= B[i][j];
return (*this);
}
Matrix& operator*=(const Matrix& B)
{
size_t n = height(), m = B.width(), p = width();
assert(p == B.height());
vector<vector<T>> C(n, vector<T>(m, 0));
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++)
for (int k = 0; k < p; k++)
C[i][j] = (C[i][j] + (*this)[i][k] * B[k][j]) % mod;
A.swap(C);
return (*this);
}
Matrix& operator^=(long long k)
{
Matrix B = Matrix::I(height());
while (k > 0)
{
if (k & 1)
B *= *this;
*this *= *this;
k >>= 1LL;
}
A.swap(B.A);
return (*this);
}
Matrix operator+(const Matrix& B) const {
return (Matrix(*this) += B);
}
Matrix operator-(const Matrix& B) const {
return (Matrix(*this) -= B);
}
Matrix operator*(const Matrix& B) const {
return (Matrix(*this) *= B);
}
Matrix operator^(const long long k) const {
return (Matrix(*this) ^= k);
}
friend ostream& operator<<(ostream& os, Matrix& p) {
size_t n = p.height(), m = p.width();
for (int i = 0; i < n; i++) {
os << "[";
for (int j = 0; j < m; j++) {
os << p[i][j] << (j + 1 == m ? "]\n" : ",");
}
}
return (os);
}
T determinant() {
Matrix B(*this);
assert(width() == height());
T ret = 1;
for (int i = 0; i < width(); i++) {
int idx = -1;
for (int j = i; j < width(); j++) {
if (B[j][i] != 0) idx = j;
}
if (idx == -1) return (0);
if (i != idx) {
ret *= -1;
swap(B[i], B[idx]);
}
ret *= B[i][i];
T vv = B[i][i];
for (int j = 0; j < width(); j++) {
B[i][j] /= vv;
}
for (int j = i + 1; j < width(); j++) {
T a = B[j][i];
for (int k = 0; k < width(); k++) {
B[j][k] -= B[i][k] * a;
}
}
}
return (ret);
}
};
pair<long long,long long> solve(long long N) {
long long now = 1LL;
for (int i = 0; i < 62; i++) {
if (N < now) {
long long ans = now / 2LL;
return { ans,N - ans };
}
now *= 2LL;
}
return { 0,0 };
}
signed main()
{
int T; cin >> T;
for (int i = 0; i < T; i++) {
long long N; cin >> N;
pair<long long,long long> ans = solve(N);
long long now = 1LL;
pair<long long, long long>ans_ = { 0, 0 };
for (int j = 0; j < 62; j++) {
if (N < now) {
ans_ = solve(now / 2LL - 1);
break;
}
now *= 2LL;
}
if (ans.second * 2 > ans_.second) {
cout << ans.first << ' ' << ans.second << endl;
}
else {
cout << ans_.first << ' ' << ans_.second << endl;
}
}
}