// @param m `1 <= m` // @return x mod m constexprlonglongsafe_mod(longlong x, longlong m){ x %= m; if (x < 0) x += m; return x; }
// Fast modular multiplication by barrett reduction // Reference: https://en.wikipedia.org/wiki/Barrett_reduction // NOTE: reconsider after Ice Lake structbarrett { unsignedint _m; unsignedlonglong im;
// @param m `1 <= m < 2^31` barrett(unsignedint m) : _m(m), im((unsignedlonglong)(-1) / m + 1) {}
// @return m unsignedintumod()const{ return _m; }
// @param a `0 <= a < m` // @param b `0 <= b < m` // @return `a * b % m` unsignedintmul(unsignedint a, unsignedint b)const{ // [1] m = 1 // a = b = im = 0, so okay
// [2] m >= 2 // im = ceil(2^64 / m) // -> im * m = 2^64 + r (0 <= r < m) // let z = a*b = c*m + d (0 <= c, d < m) // a*b * im = (c*m + d) * im = c*(im*m) + d*im = c*2^64 + c*r + d*im // c*r + d*im < m * m + m * im < m * m + 2^64 + m <= 2^64 + m * (m + 1) < 2^64 * 2 // ((ab * im) >> 64) == c or c + 1 unsignedlonglong z = a; z *= b; #ifdef _MSC_VER unsignedlonglong x; _umul128(z, im, &x); #else unsignedlonglong x = (unsignedlonglong)(((unsigned __int128)(z)*im) >> 64); #endif unsignedint v = (unsignedint)(z - x * _m); if (_m <= v) v += _m; return v; } };
// @param n `0 <= n` // @param m `1 <= m` // @return `(x ** n) % m` constexprlonglongpow_mod_constexpr(longlong x, longlong n, int m){ if (m == 1) return0; unsignedint _m = (unsignedint)(m); unsignedlonglong r = 1; unsignedlonglong y = safe_mod(x, m); while (n) { if (n & 1) r = (r * y) % _m; y = (y * y) % _m; n >>= 1; } return r; }
// Reference: // M. Forisek and J. Jancina, // Fast Primality Testing for Integers That Fit into a Machine Word // @param n `0 <= n` constexprboolis_prime_constexpr(int n){ if (n <= 1) returnfalse; if (n == 2 || n == 7 || n == 61) returntrue; if (n % 2 == 0) returnfalse; longlong d = n - 1; while (d % 2 == 0) d /= 2; constexprlonglong bases[3] = {2, 7, 61}; for (longlong a : bases) { longlong t = d; longlong y = pow_mod_constexpr(a, t, n); while (t != n - 1 && y != 1 && y != n - 1) { y = y * y % n; t <<= 1; } if (y != n - 1 && t % 2 == 0) { returnfalse; } } returntrue; } template <int n> constexprbool is_prime = is_prime_constexpr(n);
// @param b `1 <= b` // @return pair(g, x) s.t. g = gcd(a, b), xa = g (mod b), 0 <= x < b/g constexpr std::pair<longlong, longlong> inv_gcd(longlong a, longlong b){ a = safe_mod(a, b); if (a == 0) return {b, 0};
// Contracts: // [1] s - m0 * a = 0 (mod b) // [2] t - m1 * a = 0 (mod b) // [3] s * |m1| + t * |m0| <= b longlong s = b, t = a; longlong m0 = 0, m1 = 1;
while (t) { longlong u = s / t; s -= t * u; m0 -= m1 * u; // |m1 * u| <= |m1| * s <= b
// [3]: // (s - t * u) * |m1| + t * |m0 - m1 * u| // <= s * |m1| - t * u * |m1| + t * (|m0| + |m1| * u) // = s * |m1| + t * |m0| <= b
auto tmp = s; s = t; t = tmp; tmp = m0; m0 = m1; m1 = tmp; } // by [3]: |m0| <= b/g // by g != b: |m0| < b/g if (m0 < 0) m0 += b / s; return {s, m0}; }
// Compile time primitive root // @param m must be prime // @return primitive root (and minimum in now) constexprintprimitive_root_constexpr(int m){ if (m == 2) return1; if (m == 167772161) return3; if (m == 469762049) return3; if (m == 754974721) return11; if (m == 998244353) return3; int divs[20] = {}; divs[0] = 2; int cnt = 1; int x = (m - 1) / 2; while (x % 2 == 0) x /= 2; for (int i = 3; (longlong)(i)*i <= x; i += 2) { if (x % i == 0) { divs[cnt++] = i; while (x % i == 0) { x /= i; } } } if (x > 1) { divs[cnt++] = x; } for (int g = 2;; g++) { bool ok = true; for (int i = 0; i < cnt; i++) { if (pow_mod_constexpr(g, (m - 1) / divs[i], m) == 1) { ok = false; break; } } if (ok) return g; } } template <int m> constexprint primitive_root = primitive_root_constexpr(m);
mint operator+() const { return *this; } mint operator-() const { returnmint() - *this; }
mint pow(longlong n)const{ assert(0 <= n); mint x = *this, r = 1; while (n) { if (n & 1) r *= x; x *= x; n >>= 1; } return r; } mint inv()const{ if (prime) { assert(_v); returnpow(umod() - 2); } else { auto eg = internal::inv_gcd(_v, m); assert(eg.first == 1); return eg.second; } }
mint operator+() const { return *this; } mint operator-() const { returnmint() - *this; }
mint pow(longlong n)const{ assert(0 <= n); mint x = *this, r = 1; while (n) { if (n & 1) r *= x; x *= x; n >>= 1; } return r; } mint inv()const{ auto eg = internal::inv_gcd(_v, mod()); assert(eg.first == 1); return eg.second; }
signedmain(){ std::ios::sync_with_stdio(false); std::cin.tie(0); int t = 1; // int res = 0; // for(int i = 1;i <= 1145;i++) res |= i; // std::cerr<<res<<'\n'; //std::cin >> t; while (t--) { solve(); std::cout.flush(); } return0; }
2.模意义下的不等式
给定一数组 a ,初始为空。定义一次操作为
将数组末尾 t 个元素删去
将元素 x 添加至数组末尾
每次操作给定 t,x,保证操作合法,求每次操作后的
i=1⨁∣a∣(j=i∑∣a∣ai)mod220
数据范围:q≤5⋅105,x≤109
首先考虑到模数,只需要考虑 20 位及以下的贡献。异或,拆位分析奇偶。
设当前位数为 d ,我们记前缀和为 Si,则对于某个位置 i,∑j=i∣a∣ai 的第 d 位是 1 的充要条件是
(S∣a∣−Si)mod2d+1≥2d(1)
因为模一个整的 k 位 2 进制数相当于将原数 k 位以上的二进制位消去。类比十进制即可证明。
S 是好维护的,我们考虑 (1) 如何维护。这是一个循环群上的不等式,先将 Si 处理为逆元,即将上式变为
using ll = longlong; constint mod[24] = {1,2,4,8,1<<4,1<<5,1<<6,1<<7,1<<8,1<<9,1<<10,1<<11,1<<12,1<<13,1<<14,1<<15,1<<16,1<<17,1<<18,1<<19,1<<20,1<<21};
//const ll mod = 1e9 + 7; // #define int long long
classbit { public: int a[1<<22]; int n; bit(int n) : n(n + 4) { for(int i = 1;i <= n;i++)a[i] = 0; }
bit() { n = 0; }
voidadd(int x, int y){ x++; for (int i = x; i <= n; i += i & -i) { a[i] += y; } } intget(int x){ x++; int res = 0; if(x <= 0) return0; for (int i = x; i; i -= i & -i) { res += a[i]; } return res; }
intget(int l, int r){ // l++,r++; l = std::max(l,0); r = std::min(n,r); if(l == 0) returnget(r); returnget(r) - get(l - 1); } };
inlinevoidread(int &x){ x = 0; char c = getchar(); while (!isdigit(c)) c = getchar(); while (isdigit(c)) x = x * 10 + c - '0', c = getchar(); }
int sum[500050]; int idx;
voidsolve(){ std::vector<bit> a(21);
auto add = [&](int x) { for (int i = 0; i < 21; i++){ int tp = x % mod[i + 1]; //std::cerr<<tp<<' '<<x<<'\n'; a[i].add(tp, 1); } };
auto rm = [&](int x) { for (int i = 0; i < 21; i++){ int tp = x % mod[i + 1]; a[i].add(tp, -1); } };
for (int i = 0; i < 21; i++) { a[i] = bit(1 << (i + 1)); } add(0);
int q; read(q); //std::stack<int> sum; while (q--) { int t, x; read(t), read(x);
for (int i = 1; i <= t; i++) rm(sum[idx]), idx--; if (idx == 0) sum[idx + 1] = x; else sum[idx + 1] = x + sum[idx]; idx++; // std::cerr<<sum.back()<<'\n';0 add(sum[idx]);
int res = 0; for (int i = 0; i < 21; i++) { int l = 0, r = 0; int l1 = 0, r1 = 0; int tp = (sum[idx] + 1) % mod[i + 1]; //if(tp == 0)tp = (1ll << (i + 1)); int tp1 = 0; if (tp < (1ll << i)) { l = tp, r = (1 << i) + tp - 1; //std::cerr<<l<<' '<<r<<'\n'; tp1 = a[i].get(l, r); } else { l = 0, r = tp - (1<<i) - 1, l1 = tp, r1 = (1 << i + 1) - 1; //std::cerr<<l<<' '<<r<<' '<<l1<<' '<<r1<<'\n'; tp1 = a[i].get(l, r) ^ a[i].get(l1, r1); } // r &= (1<<i); res |= (tp1 & 1) * (1ll << i); }
std::cout << res << '\n'; std::cout.flush(); } }
signedmain(){ //std::ios::sync_with_stdio(false); //std::cin.tie(0); int t = 1; // std::cin >> t; while (t--) { solve(); // std::cout.flush(); } // std::cout<<5 * inv(2ll) % mod<<'\n'; return0; }