Solution -「CF 1366E2」Chiori and Doll Picking (hard version)
\(\mathscr{Description}\)
Link.
给定 \(\{a_n\}\), 值域 \([0,2^m)\). 对于每个 \(i\in[0,m]\), 求有多少个 \(\{a_n\}\) 的子序列异或和恰好含有 \(i\) 个 bit. 答案模大素数.
\(n\le2\times10^5\), \(m\le53\).
\(\mathscr{Solution}\)
\newcommand{\rank}[0]{\operatorname{rank}}
\newcommand{\span}[0]{\operatorname{span}}
\]
第一个 motivation 应当来自这个诡异的 \(m\le53\), 通过一定的猜测, 我们发现只有 \(\mathcal O(2^{m/2})\) 这种复杂度勉强说得过去. 由此, 我们可以尝试在 \(m\) 上进行复杂度平衡.
取 \(\{a_n\}\) 的一组基底 \(\mathscr A\). 我们有一个平凡的 \(\mathcal O(2^{\rank(\mathscr A)})\) 的算法: 枚举 \(v\in\span(\mathscr A)\), \(\{a_n\}\) 的线性组合出 \(v\) 的方案数恒为 \(2^{n-|\mathscr A|}\), 将其贡献向 \(|v|\) 处的答案即可. 接下来只需要找到一个 \(\mathcal O(2^{m-\rank(\mathscr A)})\) 的算法就大功告成了.
设 \(A(z)=\sum_{v\in\span(\mathscr A)}z^v\), \(\hat A\) 为其 FWT 的输出向量. 由于
\]
其中叉乘为异或卷积, 下同. 所以
\]
那么
\]
进而得到
\]
回过头来, 由于
\]
所以当且仅当不存在 \(v\in\span(\mathscr A)\) 使得 \(2\nmid|v\cap k|\) 时, \(\hat A^{(k)}=2^{\rank(\mathscr A)}\), 否则 \(\hat A^{(k)}=0\). 而又显然, 这个命题中的 \(v\in\span(\mathscr A)\) 可以等价替换为 \(v\in\mathscr A\). 这时有一个 key observation: \(\{k\mid \hat A^{(k)}=2^{\rank(\mathscr A)}\}\) 是一个线性空间 (证明是容易的).
尝试构造这个空间的一个基底 \(\mathscr B\). 将 \(\mathscr A\) 扩充到 \(m\times m\) 并消元为上三角矩阵且主对角线 \(1\) 的上方被消为 \(0\), 则此时 \(\mathscr B=\mathscr A^T+I\) (即转置后主对角线取反). 没想到 motivation, 但证明同样容易. 顺带, 我们发现 \(\rank(\mathscr B)=m-\rank(\mathscr A)\) (但 \(\mathscr A,\mathscr B\) 并不一定正交, 不知道为什么很多题解这样认为), 所以差不多可以利用 \(\mathscr B\) 来求答案了.
同样设出 \(B(z)\), 根据 \(\mathscr B\) 的来源:
\]
令 \(P(z)=\sum_{v\in\span(\mathscr A)}z^{|v|}\), \(Q(z)\) 同理. 欲求
\]
其中 \([z^t]C_k(z)=[|t|=k]\). 对正逆变换提取 \(z^0\) 都不复杂, 我们利用 \(B(z)\) 手撕这个式子:
[z^k]P(z) &= 2^{\rank(\mathscr A)-m}\sum_v[z^v]B(z)\sum_t(-1)^t\binom{|v|}{t}\binom{m-|v|}{k-t} \\
&= 2^{\rank(\mathscr A)-m}\sum_s[z^s]Q(z)\sum_t(-1)^t\binom{s}{t}\binom{m-s}{k-t}.
\end{aligned}
\]
\(Q(z)\) 可以用最初的算法 \(\mathcal O(2^{\rank(\mathscr B)})\) 算出来, 平衡复杂度则得到 \(\mathcal O(2^{m/2})\) 的算法.
\(\mathscr{Code}\)
/*+Rainybunny+*/
#include <bits/stdc++.h>
#define rep(i, l, r) for (int i = l, rep##i = r; i <= rep##i; ++i)
#define per(i, r, l) for (int i = r, per##i = l; i >= per##i; --i)
typedef long long LL;
inline char fgc() {
static char buf[1 << 17], *p = buf, *q = buf;
return p == q && (q = buf + fread(p = buf, 1, 1 << 17, stdin), p == q) ?
EOF : *p++;
}
template <typename Tp = int>
inline Tp rint() {
Tp x = 0, s = fgc(), f = 1;
for (; s < '0' || '9' < s; s = fgc()) f = s == '-' ? -f : f;
for (; '0' <= s && s <= '9'; s = fgc()) x = x * 10 + (s ^ '0');
return x * f;
}
template <typename Tp>
inline void wint(Tp x) {
if (x < 0) putchar('-'), x = -x;
if (9 < x) wint(x / 10);
putchar(x % 10 ^ '0');
}
const int MAXM = 53, MOD = 998244353, INV2 = MOD + 1 >> 1;
int n, m, bino[MAXM + 5][MAXM + 5];
inline int mul(const int u, const int v) { return 1ll * u * v % MOD; }
inline void subeq(int& u, const int v) { (u -= v) < 0 && (u += MOD); }
inline int sub(int u, const int v) { return (u -= v) < 0 ? u + MOD : u; }
inline void addeq(int& u, const int v) { (u += v) >= MOD && (u -= MOD); }
inline int add(int u, const int v) { return (u += v) < MOD ? u : u - MOD; }
inline int mpow(int u, int v) {
int ret = 1;
for (; v; u = mul(u, u), v >>= 1) ret = mul(ret, v & 1 ? u : 1);
return ret;
}
struct LinearBase {
int siz;
LL bas[MAXM];
inline void insert(LL x) {
rep (i, 0, m - 1) if (x >> i & 1) {
if (!bas[i]) return bas[i] = x, ++siz, void();
x ^= bas[i];
}
}
inline std::vector<int> spanCount() const {
std::vector<int> ret(m + 1), seq; seq.reserve(siz);
rep (i, 0, m - 1) if (bas[i]) seq.push_back(i);
std::function<void(int, LL)> enumer = [&](const int id, const LL v) {
if (id == siz) return void(++ret[__builtin_popcountll(v)]);
enumer(id + 1, v), enumer(id + 1, v ^ bas[seq[id]]);
};
enumer(0, 0);
return ret;
}
inline void standardize() {
rep (i, 0, m - 1) if (bas[i]) {
rep (j, 0, i - 1) if (bas[j] >> i & 1) {
bas[j] ^= bas[i];
}
}
}
} A, B;
inline void solveA() {
int pwr = mpow(2, n - A.siz);
auto&& P = A.spanCount();
rep (i, 0, m) wint(mul(P[i], pwr)), putchar("\n "[i < m]);
}
inline void solveB() {
bino[0][0] = 1;
rep (i, 1, m) {
bino[i][0] = 1;
rep (j, 1, i) bino[i][j] = add(bino[i - 1][j - 1], bino[i - 1][j]);
}
A.standardize();
rep (i, 0, m - 1) if (!A.bas[i]) {
LL v = 1ll << i;
rep (j, 0, i - 1) v |= (A.bas[j] >> i & 1) << j;
B.insert(v);
}
int pwr = n < m ? mpow(INV2, m - n) : mpow(2, n - m);
auto&& Q = B.spanCount();
rep (i, 0, m) {
int ans = 0;
rep (j, 0, m) if (Q[j]) {
int coe = 0;
rep (k, 0, std::min(i, j)) {
(k & 1 ? subeq : addeq)(coe,
mul(bino[j][k], bino[m - j][i - k]));
}
addeq(ans, mul(coe, Q[j]));
}
wint(mul(pwr, ans)), putchar("\n "[i < m]);
}
}
int main() {
n = rint(), m = rint();
rep (i, 1, n) A.insert(rint<LL>());
if (A.siz <= m + 1 >> 1) solveA();
else solveB();
return 0;
}
Solution -「CF 1366E2」Chiori and Doll Picking (hard version)的更多相关文章
- Solution -「CF 1342E」Placing Rooks
\(\mathcal{Description}\) Link. 在一个 \(n\times n\) 的国际象棋棋盘上摆 \(n\) 个车,求满足: 所有格子都可以被攻击到. 恰好存在 \(k\ ...
- Solution -「CF 1622F」Quadratic Set
\(\mathscr{Description}\) Link. 求 \(S\subseteq\{1,2,\dots,n\}\),使得 \(\prod_{i\in S}i\) 是完全平方数,并最 ...
- Solution -「CF 923F」Public Service
\(\mathscr{Description}\) Link. 给定两棵含 \(n\) 个结点的树 \(T_1=(V_1,E_1),T_2=(V_2,E_2)\),求一个双射 \(\varph ...
- Solution -「CF 923E」Perpetual Subtraction
\(\mathcal{Description}\) Link. 有一个整数 \(x\in[0,n]\),初始时以 \(p_i\) 的概率取值 \(i\).进行 \(m\) 轮变换,每次均匀随机 ...
- Solution -「CF 1586F」Defender of Childhood Dreams
\(\mathcal{Description}\) Link. 定义有向图 \(G=(V,E)\),\(|V|=n\),\(\lang u,v\rang \in E \Leftrightarr ...
- Solution -「CF 1237E」Balanced Binary Search Trees
\(\mathcal{Description}\) Link. 定义棵点权为 \(1\sim n\) 的二叉搜索树 \(T\) 是 好树,当且仅当: 除去最深的所有叶子后,\(T\) 是满的: ...
- Solution -「CF 623E」Transforming Sequence
题目 题意简述 link. 有一个 \(n\) 个元素的集合,你需要进行 \(m\) 次操作.每次操作选择集合的一个非空子集,要求该集合不是已选集合的并的子集.求操作的方案数,对 \(10^9 ...
- Solution -「CF 1023F」Mobile Phone Network
\(\mathcal{Description}\) Link. 有一个 \(n\) 个结点的图,并给定 \(m_1\) 条无向带权黑边,\(m_2\) 条无向无权白边.你需要为每条白边指定边权 ...
- Solution -「CF 599E」Sandy and Nuts
\(\mathcal{Description}\) Link. 指定一棵大小为 \(n\),以 \(1\) 为根的有根树的 \(m\) 对邻接关系与 \(q\) 组 \(\text{LCA}\ ...
- Solution -「CF 487E」Tourists
\(\mathcal{Description}\) Link. 维护一个 \(n\) 个点 \(m\) 条边的简单无向连通图,点有点权.\(q\) 次操作: 修改单点点权. 询问两点所有可能路 ...
随机推荐
- kubectl常用命令(二)
四.进入容器 # 进入pod容器,但是对权限要求也较多 kubectl exec -it podName sh # 通过bash获得 pod 中某个容器的TTY,相当于登录容器 kubectl exe ...
- 异源数据同步 → DataX 同步启动后如何手动终止?
开心一刻 刚刚和老婆吵架,气到不行,想离婚女儿突然站出来劝解道:难道你们就不能打一顿孩子消消气,非要闹离婚吗?我和老婆同时看向女儿,各自挽起了衣袖女儿补充道:弟弟那么小,打他,他又不会记仇 需求背景 ...
- 【FAQ】HarmonyOS SDK 闭源开放能力 —Vision Kit
1.问题描述: 人脸活体检测页面会有声音提示,如何控制声音开关? 解决方案: 活体检测暂无声音控制开关,但可通过其他能力控制系统音量,从而控制音量. 活体检测页面固定音频流设置的是8(无障碍),获取的 ...
- Flink window
窗口计算 我们经常需要在一个时间窗口维度上对数据进行聚合,窗口是流处理应用中经常需要解决的问题.Flink的窗口算子为我们提供了方便易用的API,我们可以将数据流切分成一个个窗口,对窗口内的数据进行处 ...
- IDEA方法模板、类模板设置记录
类模板 设置入口 Mac:common+,进入设置->Editor->File and Code Templates->Includes 模版代码 /** * todo * * @a ...
- 70 个群都来问我的 AI 日报,是这么做的。
最近我给 FastGPT 用户交流群里接入了 AI 日报,每天早上 10 点会自动向群里推送 AI 日报,让群里的小伙伴们第一时间了解到昨天 AI 领域都发生了哪些大事. 效果大概是这个样子的: 如果 ...
- pnpm 是如何颠覆 npm 和 yarn 的?
今天研究了一下 pnpm 的机制,发现它确实很强大,甚至可以说对 yarn 和 npm 形成了降维打击 . 我们从包管理工具的发展历史,一起看下到底好在哪里? npm2 在 npm 3.0 版本之前, ...
- 深入JVM的Class文件结构
Class文件由顺序的8位字节为基础单位构成的二进制流.各个项目严格按照顺序紧凑排列,无分隔符. 需要用8位字节以上空间数据项时按照高位在前分割成若干个8位字节存储. 只包含2种数据类型: 无符号数 ...
- 使用 ASM 实现 Java 语言的“多重继承”
问题的提出 在大部分情况下,需要多重继承往往意味着糟糕的设计.但在处理一些遗留项目的时候,多重继承可能是我们能做出的选择中代价最小的.由于 Java 语言本身不支持多重继承,这常常会给我们带来麻烦,最 ...
- k8s之常用命令
Minikube # 启动集群服务 minikube start # 查看集群服务状态 minikube status# 登录集群minikube ssh # 关闭,暂停,恢复,删除集群服务 mini ...