結果
問題 | 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';}