結果

問題 No.2990 Interval XOR
ユーザー Kude
提出日時 2024-12-23 22:44:04
言語 C++23
(gcc 13.3.0 + boost 1.87.0)
結果
AC  
実行時間 825 ms / 2,000 ms
コード長 4,549 bytes
コンパイル時間 4,887 ms
コンパイル使用メモリ 293,908 KB
実行使用メモリ 31,516 KB
最終ジャッジ日時 2024-12-23 22:44:22
合計ジャッジ時間 15,854 ms
ジャッジサーバーID
(参考情報)
judge5 / judge3
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample AC * 3
other AC * 37
権限があれば一括ダウンロードができます

ソースコード

diff #
プレゼンテーションモードにする

#include<bits/stdc++.h>
namespace {
#pragma GCC diagnostic ignored "-Wunused-function"
#include<atcoder/all>
#pragma GCC diagnostic warning "-Wunused-function"
using namespace std;
using namespace atcoder;
#define rep(i,n) for(int i = 0; i < (int)(n); i++)
#define rrep(i,n) for(int i = (int)(n) - 1; i >= 0; i--)
#define all(x) begin(x), end(x)
#define rall(x) rbegin(x), rend(x)
template<class T> bool chmax(T& a, const T& b) { if (a < b) { a = b; return true; } else return false; }
template<class T> bool chmin(T& a, const T& b) { if (b < a) { a = b; return true; } else return false; }
using ll = long long;
using P = pair<int,int>;
using VI = vector<int>;
using VVI = vector<VI>;
using VL = vector<ll>;
using VVL = vector<VL>;
using mint = modint998244353;
struct S {
mint v0, v1;
friend S operator+(const S& lhs, const S& rhs) { return {lhs.v0 + rhs.v0, lhs.v1 + rhs.v1}; }
friend S operator-(const S& lhs, const S& rhs) { return {lhs.v0 - rhs.v0, lhs.v1 - rhs.v1}; }
friend S operator*(const S& lhs, const S& rhs) { return {lhs.v0 * rhs.v0 + lhs.v1 * rhs.v1, lhs.v0 * rhs.v1 + lhs.v1 * rhs.v0}; }
bool is_zero() { return v0 == 0 && v1 == 0; }
S& operator*=(const S& rhs) { return *this = *this * rhs; }
S& operator-=(const S& rhs) { return *this = *this - rhs; }
S& operator*=(mint v) { v0 *= v, v1 *= v; return *this; }
};
struct Factor {
int x1, x2;
S c1, c2;
};
struct ProdRes {
int x0;
vector<int> basis;
vector<S> dist;
};
ProdRes two_term_poly_xor_product(const vector<Factor>& d) {
using mint = S;
vector<array<mint, 2>> dp{{S{1}, S{1}}};
int x0 = 0;
vector<int> basis;
for (auto [x1, x2, c1, c2] : d) {
if (c1.is_zero() || c2.is_zero()) {
mint v;
if (!c1.is_zero()) x0 ^= x1, v = c1;
else if (!c2.is_zero()) x0 ^= x2, v = c2;
else return ProdRes{0, {}, {S{}}};
dp[0][0] *= v;
dp[0][1] *= v;
continue;
}
x0 ^= x1;
int x = x1 ^ x2, choice = 0, k = 0;
for (int b : basis) {
if (chmin(x, x ^ b)) choice ^= 1 << k;
k++;
}
if (x) {
basis.emplace_back(x);
choice ^= 1 << k;
dp.resize(1 << size(basis), {S{1}, S{1}});
}
dp[choice][0] *= c1 + c2;
dp[choice][1] *= c1 - c2;
}
int n2 = 1 << ssize(basis);
for (int k2 = 1; k2 < n2; k2 *= 2) {
for (int di = 2 * k2, i_high = 0; i_high < n2; i_high += di) {
for (int i_low = 0; i_low < k2; i_low++) {
int i0 = i_low | i_high, i1 = i0 | k2;
auto d0 = dp[i0], d1 = dp[i1];
dp[i0] = {d0[0] * d1[0], d0[1] * d1[1]};
dp[i1] = {d0[0] * d1[1], d0[1] * d1[0]};
}
}
}
vector<mint> dist(n2);
for (int i = 0; i < n2; i++) dist[i] = dp[i][0];
for (int k2 = 1; k2 < n2; k2 *= 2) {
for (int di = 2 * k2, i_high = 0; i_high < n2; i_high += di) {
for (int i_low = 0; i_low < k2; i_low++) {
int i0 = i_low | i_high, i1 = i0 | k2;
auto v0 = dist[i0], v1 = dist[i1];
dist[i0] = v0 + v1, dist[i1] = v0 - v1;
}
}
}
auto iz = atcoder::modint998244353(2).inv().pow(ssize(basis));
for (int i = 0; i < n2; i++) dist[i] *= iz;
return ProdRes{x0, move(basis), move(dist)};
}
} int main() {
ios::sync_with_stdio(false);
cin.tie(0);
int n, m;
cin >> n >> m;
int n2 = 1 << n;
struct S { int l1, r1, l2, r2; };
vector<S> d(m);
vector<mint> dp(n2);
dp[0] = 1;
rep(i, m) {
int l, r;
cin >> l >> r;
r++;
int c = -bit_floor(1U * l ^ r) & r;
d[i] = {l, c, c, r};
dp[0] *= r - l;
}
const mint inv2 = mint(2).inv();
rrep(k, n) {
vector<Factor> fs(m);
for (int i = 0; auto& [l1, r1, l2, r2] : d) {
if (r1 - l1 >= 1 << (k + 1)) r1 -= 1 << (k + 1);
if (r2 - l2 >= 1 << (k + 1)) l2 += 1 << (k + 1);
int c1 = (l1 >> k | 1) << k, c2 = (l2 >> k | 1) << k;
fs[i++] = {l1 >> (k + 1) << (k + 1), l2 >> (k + 1) << (k + 1), {min(r1, c1) - min(l1, c1), max(r1, c1) - max(l1, c1)}, {min(r2, c2) - min(l2,
          c2), max(r2, c2) - max(l2, c2)}};
}
auto [x0, basis, dist] = two_term_poly_xor_product(fs);
int sz = ssize(basis);
VI idx(1 << sz);
rep(i, sz) idx[1 << i] = basis[i];
rep(i, 1 << sz) {
int j = i & -i;
idx[i] = idx[j] ^ idx[i ^ j];
}
rep(i, 1 << sz) idx[i] ^= x0;
rep(i, 1 << sz) dp[idx[i]] -= dist[i].v0 + dist[i].v1;
for (int di = 1 << (k + 1), i = 0; i < n2; i += di) dp[i] *= inv2, dp[i | 1 << k] += dp[i];
rep(i, 1 << sz) dp[idx[i]] += dist[i].v0, dp[idx[i] | 1 << k] += dist[i].v1;
}
for (auto x : dp) cout << x.val() << '\n';
}
הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
0