当前位置: 首页 > news >正文

题解:CF1336E2 Chiori and Doll Picking (hard version)

很牛很牛很牛的题。

题意:给出 \(n\) 个数 \(a_i\),保证 \(a_i<2^m\),问对于 \(i\in[0,m]\),从这 \(n\) 个数取出若干个异或值的 \(1\) 的个数为 \(i\) 的方案数。\(n\le 2\times 10^5,m\le 53\)

做法:

首先我们先将所有数插入线性基,然后有个经典结论,如果线性基的大小为 \(k\),那么集合的异或和有 \(2^k\) 种,并且每种都有 \(2^{n-k}\) 个。这个比较显然,因为线性基里的元都是不相关的,所以随意取或不取都对应不同的元素,而集合外的也随意取,容易理解。

然后我们就有一个 \(2^k\) 的做法,直接枚举集合内异或和即可。

然后我们现在会再提出来一个 \(2^{m-k}\) 的做法,这样直接对数据分治就是根号值域的。

首先定义一些东西,\(\operatorname{cnt}(x)\) 代表 \(x\) 在二进制下 \(1\) 的个数。\(FWT(F)\) 代表 \(F\)\(F\) 这个集合幂级数做一次 FWT,\(IFWT(F)\) 类似定义。

我们记 \(Z(S)\) 代表 \(S\) 能构成的异或和的集合,\(F(S)=\sum\limits_{i\in Z(S)}x^i,G_c(S)=\sum\limits_{i\in Z(S),\operatorname{cnt}(i)=c} x ^i\)。那么很自然地,算 \(1\) 的个数为 \(x\) 的答案就是 \(F(S)\times G_{x}(S)[x^0]\),这里的乘法是异或卷积,以下也默认异或卷积,点乘是对位乘法。

直接做这个东西显然太困难了,我们考虑发掘一下 \(F,G\) 的性质。

  • \(FWT(F)\) 中每个元素只有可能是 \(0,2^k\)

考虑 \(F\times F\) 的意义,其 \(i\) 次项的系数应该是 \(2^k[i\in Z(S)]\),因为在 \(S\) 中的元素要异或成 \(i\) 应该只能由唯一一个与其配对成 \(i\),所以方案数就是随意选一个数,也就是 \(2^k\)。整体写出来会有 \(F\times F=2^kF\)

然后考虑对这个东西取 \(FWT\),得到:\(FWT(F)\cdot FWT(F)=2^kFWT(F)\),显然只有这两种取法。

  • \(FWT_i(F)\) 的取值为 \(2^k\),则 \(\forall j\in Z(S),\operatorname{cnt}(i\land j) \equiv0\pmod 2\)

考虑 fwt 的本质,\(FWT_i(F)=\sum\limits_{j=0}-1^{\operatorname{cnt}(i\land j)} F_j\),因为 \(F\) 只有 \(2^k\) 项为 \(1\),所以必须要全部取 \(1\) 而不是 \(-1\)。也就是全都是偶数。

  • 所有满足 \(FWT_i(F)\) 不为 \(0\) 的位置构成一个线性基所张出的所有元素。

这个比较显然,因为考虑 \(i,j\) 都满足,那 \(i\oplus j\) 也满足。

  • 我们可以构造一个大小为 \(n-k\) 大小的线性基去构成满足上面这个条件的所有数。

考虑根据上面的证明,其实我们只需要找出一组基满足他们这些位不为 \(0\) 就可以,接下来我们给出构造。

我们先对线性基进行高消,显然是不改变线性基的形态的,然后考虑对于其他的非基位,假设是第 \(i\) 行,我们先令 \((i,i)\) 这一位为 \(1\),然后为了和原基的 \(\operatorname{cnt}\) 保持为 \(2\),目前有些和 \(i\) 行的基交为 \(1\),假设是第 \(j\) 行,那么我们直接令 \((i,j)\) 这个位置为 \(1\),注意到对于原基的第 \(x,y\) 行,\((x,y),(y,x)\) 都一定为 \(0\),因为我们做了高消,所以我令 \((i,j)\)\(1\) 只会影响第 \(i\) 行和第 \(j\) 行的基求交的奇偶性,用这个构造出来的新基就是合法的。

那么我们现在就知道 \(FWT(F)\) 在哪些位置上有 \(2^k\) 的权了。现在的问题是 \(FWT(G_c)\),我们也去找找性质。

我们考虑 \(FWT_i(G_c)\) 怎么求,展开是 \(\sum\limits_{j=0}-1^{\operatorname{cnt}(i\land j)} G_c[j]\),我们直接去枚举 \(\operatorname{cnt}(i\land j)\),然后去分配 \(1\) 的位,可以得到答案是 \(\sum\limits_{k=0}-1^k\binom{\operatorname{cnt}(i)}{k}\binom{m-\operatorname{cnt}(i)}{c-k}\)

有了 \(FWT(F),FWT(G_c)\) 我们就可以去算答案了,我们直接写出来柿子:

\[ans_c=2^{n-k}[x^0]FG_c=2^{n-k}[x^0]IFWT(FWT(F)FWT(G_c)) \]

注意到 \(IFWT(X)[x^0]=\frac{1}{2^m}FWT(X)[x^0]\)\(X\) 是一个集合幂级数。

我们可以直接展开得到:

\[ans_c=\frac{1}{2^m}2^{n-k}[x^0](\sum_{i\in Z(S')}2^k\sum_{t=0}-1^t\binom{\operatorname{cnt}(i)}{t}\binom{m-\operatorname{cnt}(i)}{c-t} \]

\(S'\) 是新基。

直接按上述过程计算即可,后面这个部分注意到只跟 \(\operatorname{cnt}(i),c\) 有关,可以提前预处理。

代码:

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int maxn = 2e5 + 5, mod = 998244353;
int n, m, d[maxn], cnt, C[105][105], mx, f;
int qpow(int x, int k, int p) {int res = 1;while(k) {if(k & 1)res = res * x % p;x = x * x % p, k >>= 1;}return res;
}
void insert(int x) {for (int i = m; i >= 0; i--) {if((x >> i) & 1) {if(!d[i]) {d[i] = x;cnt++;break;}x ^= d[i];}}
}
int ans[maxn];
inline int popcnt(int x) {int cnt = 0;while(x)cnt += x & 1, x /= 2;return cnt;
}
void solve1(int nw, int tot) {if(nw > m) {ans[__builtin_popcountll(tot)]++;return ;}solve1(nw + 1, tot);if(d[nw])solve1(nw + 1, tot ^ d[nw]);
}
int w[maxn], t[maxn];
void solve2(int nw, int tot) {if(nw > m) {w[__builtin_popcountll(tot)]++;return ;}solve2(nw + 1, tot);if(t[nw])solve2(nw + 1, tot ^ t[nw]);
}
int dp[105][105];
inline int Comb(int m, int n) {if(m < 0 || n < 0 || m < n)return 0;return C[m][n];
}
signed main() {ios::sync_with_stdio(false);cin >> n >> m;C[0][0] = 1;for (int i = 1; i <= m; i++) {C[i][0] = 1;for (int j = 1; j <= m; j++) C[i][j] = (C[i - 1][j - 1] + C[i - 1][j]) % mod;}for (int i = 1; i <= n; i++) {int x; cin >> x;insert(x);f |= (i == 1 && x == 4413858567421951);}
//	cout << cnt << endl;if(cnt <= 27)solve1(0, 0);else {for (int i = 0; i <= m; i++)for (int j = i + 1; j <= m; j++)if((d[j] >> i) & 1)d[j] ^= d[i];for (int i = 0; i <= m - 1; i++) {if(d[i])continue;t[i] = (1ll << i);for (int j = 0; j <= m; j++) {if(d[j] && ((d[j] >> i) & 1))t[i] |= (1ll << j);}}for (int i = 0; i <= m; i++)for (int j = 0; j <= m; j++)for (int k = 0; k <= m; k++)dp[i][j] = (dp[i][j] + (k % 2 ? mod - 1 : 1) * Comb(j, k) % mod * Comb(m - j, i - k) % mod) % mod;for (int i = 0; i <= m; i++)for (int j = 0; j <= m; j++)ans[j] = (ans[j] + dp[j][i] * w[i]) % mod;for (int i = 0; i <= m; i++)ans[i] = qpow(2, cnt, mod) * ans[i] % mod * qpow(qpow(2, m, mod) % mod, mod - 2, mod) % mod;}for (int i = 0; i <= m; i++)cout << ans[i] * qpow(2, n - cnt, mod) % mod << " ";return 0;
}
http://www.hskmm.com/?act=detail&tid=34281

相关文章:

  • Apollo自动驾驶平台:开源、高性能的自动驾驶解决方案
  • 三八皇后、8线程、MMX
  • MantisBT vs Kanass,开源项目管理工具一文全面对比分析 - 详解
  • 2025工作服厂家推荐:深圳市贵格服饰,专业定制各类高品质工作服!
  • 2025年陶瓷过滤机厂家推荐排行榜,陶瓷真空过滤机/盘式陶瓷过滤机/矿用陶瓷过滤机/全自动陶瓷过滤机/固液分离设备公司精选
  • 2019年机器学习研究奖项获奖名单公布
  • 2025不锈钢清洗钝化液推荐:隆彦商贸环保高效,品质卓越!
  • 2025年棋牌室加盟推荐排行榜,自主棋牌室加盟,自助棋牌室加盟,优选品牌与服务指南
  • 2025年轻钢龙骨厂家,铝方通厂家,铝单板厂家,石膏板厂家推荐排行榜:专业品质与服务口碑之选!
  • 013的加密世界权威指南_第一部分
  • 卸载安装JDK
  • 2025年给汤机厂家最新权威推荐榜:诚信价格与卓越性能的完美结合,优质给汤机公司精选
  • 2025年给汤机厂家最新权威推荐榜:靠谱给汤机源头厂家精选,高效稳定与售后服务深度解析
  • DOS命令
  • windows防火墙开放某个端口的配置方法
  • 2025铝单板厂家推荐杰兰斯装饰,专业定制异形双曲等多款铝单板!
  • 条件运算符的中间表达式省略扩展
  • 2025年网络营销推广服务商权威推荐榜单,网络推广,网络营销,专业服务与效果保障之选!
  • day18-课程介绍+环境适配
  • 动态规划做题记录
  • 高级语言程序设计低第一次作业
  • 2025年棒球帽,卫衣,羽绒服生产厂家推荐排行榜,时尚舒适与品质保证的首选!
  • 2025年南京网站建设服务商权威推荐榜单,专业建站与优质服务口碑之选
  • Deepspeed遇到的问题
  • CF1789B Serval and Inversion Magic
  • springboot配置拦截器,实现用户未登录不能访问其他页面
  • 2025卫衣厂家口碑推荐:COVERNAT乐酷天品质卓越,时尚舒适首选!
  • 2025年工作服厂家推荐排行榜,防静电/劳保/国网/餐厅/工厂/电工/防酸碱/电力/车间/航空/员工/文化衫/T恤/POLO衫/冲锋衣工作服公司推荐!
  • 岐金兰AI元人文构想的系统化研究:理论创新与实践挑战
  • AtCoder Beginner Contest 391