Codeforces Round #635 (Div. 1)
A
略
B
先排序,枚举 \(x\),贪心地选 \(y,z\)
C
\(S\) 中连续的一段在 \(A\) 中也是连续的。想象把 \(T\) 补齐(后面是什么无所谓),令 \(f_{l,r}\) 表示 \(S[1,r-l+1]\) 拼成 \(T[l,r]\) 的方案数,正常转移即可
D
投入 \(x\),若 \(triplet\) 的增量 \(>0\),容易得出 \(x\) 的数量,但若 \(=0\),无法得知有 \(0\) 个还是 \(1\) 个,需要再加一次询问。考虑用上 \(straight\),然后 \(\dots\dots\) 不扯了,直接说做法吧
如果顺着“然后”想下去,会发现这个问题最麻烦的地方是会出现 \(0\),\(0x=0\) 有无穷多解。先按照 \(n-1,n-2,\dots3\) 的顺序放一遍,这样起码有 \(1\),并得到每次的 \(straight\) 增量 \(a_{i-2}a_{i-1}+a_{i-1}(a_{i+1}+1)+(a_{i+1}+1)(a_{i+2}+1)\)。先来个 \(1\) 得出 \(a_2(a_3+1)\),再来个 \(2\) 获得 \((a_1+1)(a_3+1)+(a_3+1)(a_4+1)=(a_3+1)(a_1+a_4+2)\),再来个 \(1\) 弄出 \(a_1\) 和 \((a_2+1)(a_3+1)\)。这样可以推出 \(a_1,a_2,a_3\)。再根据之前 \(n-1,n-2\dots3\) 的增量可以解出所有。似乎并不需要特判 \(n=4\)
#include <bits/stdc++.h>
using namespace std;
const int N = 105;
int n, a[N], c[N], lap, laq;
pair<int, int> ask (int x) {
printf ("+ %d\n", x); fflush (stdout);
int p, q; cin >> p >> q;
int ta = p - lap, tb = q - laq;
lap = p, laq = q;
return make_pair (ta, tb);
}
void print () {
putchar ('!');
for (int i = 1; i <= n; ++i) printf (" %d", c[i]); puts ("");
fflush (stdout);
}
int C (int x) {
return x > 2 ? x * (x - 1) * (x - 2) / 6 : 0;
}
signed main() {
cin >> n >> lap >> laq;
for (int i = n - 1; i >= 3; --i) a[i] = ask (i).second;
int A = ask (1).second; // c2(c3+1) c2c3+c2
int B = ask (2).second; // (c3+1)(c1+c4+2)
pair<int, int> t = ask (1);
for (int i = 2; i <= n + 2; ++i) {
if (C (i) - C (i - 1) == t.first) c[1] = i - 2;
}
int C = t.second; // (c2+1)(c3+1) c2c3+c2+c3+1
c[3] = C - A - 1;
c[2] = A / (c[3] + 1);
c[4] = B / (c[3] + 1) - c[1] - 2;
// a[i] c{i-2}c{i-1}+c{i-1}(c{i+1}+1)+(c{i+1}+1)(c{i+2}+1)
for (int i = 3; i < n - 1; ++i) {
int t = a[i] - c[i - 1] * (c[i - 2] + c[i + 1] + 1);
c[i + 2] = t / (c[i + 1] + 1) - 1;
}
return ++c[n], print (), 0;
}
E1
基本结论:若插入 \(n\) 个数建立的线性基为 \(S\),则能够通过异或得到的数有 \(2^{|S|}\) 个,而得到这些数的方案数均为 \(2^{n-|S|}\)。
进行折半搜索,对于线性基中前 \(\frac{m}{2}\) 位的向量爆搜 \(f_i\) 表示 \(i\) 是否可以异或出来。后 \(\frac{m}{2}\) 位爆搜出 \(g_{i,j}\) 表示可以异或出有多少个 \(x\) 满足高 \(\frac{m}{2}\) 位有 \(i\) 个 \(1\),低 \(\frac{m}{2}\) 位为 \(j\)。然后枚举 \(i\),用异或 \(fwt\) 合并 \(g_{i,j}\) 和 \(f_j\)。复杂度 \(O(2^{0.5m}m^2)\)
#define int long long
const int N = 2e5 + 5, M = 36, P = 1 << 19, mod = 998244353;
int n, m, cc, d[M + 5], res[M];
void insert (int x) {
for (int i = m - 1; ~i; --i)
if (x >> i & 1) {
if (d[i]) x ^= d[i];
else { d[i] = x, ++cc; break; }
}
}
int mid, f[P], g[19][P], ff[P], cnt[P], two;
void dfs1 (int x, int s) {
if (x >= mid) { ++f[s]; return; }
dfs1 (x + 1, s);
if (d[x]) dfs1 (x + 1, s ^ d[x]);
}
void dfs2 (int x, int s) {
if (x >= m) {
++g[cnt[s >> mid]][s & ((1 << mid) - 1)]; return;
}
dfs2 (x + 1, s);
if (d[x]) dfs2 (x + 1, s ^ d[x]);
}
#define up(x, y) ((x += y) >= mod && (x -= mod))
void prework () {
cnt[0] = 0;
for (int i = 1; i < (1 << mid + 1); ++i)
cnt[i] = cnt[i >> 1] + (i & 1);
two = 1;
for (int i = 1; i <= n - cc; ++i) up (two, two);
}
int qpow (int x, int y) {
int t = 1;
while (y) {
if (y & 1) t = t * x % mod;
x = x * x % mod, y >>= 1;
}
return t;
}
int inv = qpow (2, mod - 2);
void fwt (int *a, int opt) {
for (int i = 2; i <= (1 << mid); i <<= 1)
for (int p = i >> 1, j = 0; j < (1 << mid); j += i)
for (int k = j; k < j + p; ++k) {
int x = a[k], y = a[k + p];
a[k] = (x + y) % mod, a[k + p] = (x - y + mod) % mod;
if (opt < 0) (a[k] *= inv) %= mod, (a[k + p] *= inv) %= mod;
}
}
signed main() {
read (n), read (m);
for (int i = 1, x; i <= n; ++i) read (x), insert (x);
mid = (m + 1) / 2; prework ();
dfs1 (0, 0), dfs2 (mid, 0);
memcpy (ff, f, sizeof (f));
for (int i = 0; i <= m - mid; ++i) {
memcpy (f, ff, sizeof (f));
fwt (f, 1), fwt (g[i], 1);
for (int j = 0; j < (1 << mid); ++j)
(f[j] *= g[i][j]) %= mod;
fwt (f, -1);
for (int j = 0; j < (1 << mid); ++j)
up (res[i + cnt[j]], f[j]);
}
for (int i = 0; i <= m; ++i)
printf ("%lld ", res[i] * two % mod);
return 0;
}
E2
数学题咕咕咕
F
心情好了就补