結果
問題 | No.2990 Interval XOR |
ユーザー |
![]() |
提出日時 | 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 |
ソースコード
#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'; }