题目链接

https://codeforces.com/contest/1336/problem/E

题解

假设线性基大小是 \(L\),其异或值域记作 \(S\),则对于异或值域内每个数,显然有 \(2^{n-L}\) 种方案异或得到。因此只需要建一组线性基然后对这个线性基求答案即可,相当于 \(n\le m\).
数据分治。
算法一:
暴力枚举每个元素选不选。
时间复杂度 \(O(2^L)\).
算法二:
记录非自由元的状态进行状压 DP.
时间复杂度 \(O(2^{m-L}m^2)\).
结合算法一和算法二,可以通过 E1 题。
算法三:
下面约定某个数组 FWT 后的数组用对应的大写字母表示。
设长为 \(2^m\) 的数组 \(b_k[i]=[\text{bitcnt}(i)=k]\),\(c[i]=[i\in S]\)。
则 \(k\) 的答案为 \(b_k\) 和 \(c\) 异或卷积后为 \(0\) 的位置上的值,即 \(\frac{1}{2^m}\sum^{2^m-1}_{i=0}B_k[i]C[i]\).
根据 FWT 的定义,易得 \(B_k[i]=\sum^{2^m-1}_{j=0}(-1)^{\text{bitcnt}(i\& j)}[\text{bitcnt}(j)=k]=\sum^{\text{bitcnt}(i)}_{j=0}(-1)^j{\text{bitcnt}(i)\choose j}{m-\text{bitcnt}(i)\choose k-j}\),即 \(B_k[i]\) 只和 \(\text{bitcnt}(i)\) 有关,可以在关于 \(m\) 的多项式时间内求出。
现在考虑如何求 \(C\): \(C[i]=\sum_{x\in S} (-1)^{\text{bitcnt}(i\& x)}\),不难观察到若存在线性基里的一个元素与 \(i\) 的 \(\text{and}\) 的 \(\text{bitcnt}\) 为奇数,则该值一定为 \(0\)(映射法易证),否则为 \(2^L\). 那么只有那些与线性基里的每个元素 \(\text{and}\) 的 \(\text{bitcnt}\) 都为偶数的 \(i\) 有用。而满足这个条件的 \(i\) 显然不能包含任何一个自由元,因此不超过 \(2^{m-L}\) 个,可以直接爆搜。要求的是和 \(B_k\) 点积后的结果,而 \(B_k[i]\) 的取值只和 \(\text{bitcnt(i)}\) 有关,因此只需要对每个 \(\text{bitcnt}\) 统计出 \(C_i\) 的和即可。
时间复杂度 \(O(2^{m-L}+m^3)\).
结合算法一和算法三,可以通过 E2 题。
时间复杂度 \(O(2^{\frac{m}{2}}+m^3+nm)\).

算法三最难想的是第一步吧……异或的性质好神奇,Sooke 好强!

代码

#include<bits/stdc++.h>
#define llong long long
#define mkpr make_pair
#define iter iterator
#define riter reversed_iterator
#define y1 Lorem_ipsum_dolor
using namespace std;inline int read()
{int x = 0,f = 1; char ch = getchar();for(;!isdigit(ch);ch=getchar()) {if(ch=='-') f = -1;}for(; isdigit(ch);ch=getchar()) {x = x*10+ch-48;}return x*f;
}const int mxN = 1<<19;
const int mxM = 53;
const int P = 998244353;
llong comb[mxM+3][mxM+3];
int bitcnt[mxN+3];
llong a[mxM+3]; int b[mxM+3];
llong ans[mxM+3];
int n,m,sz;llong quickpow(llong x,llong y)
{llong cur = x,ret = 1ll;for(int i=0; y; i++){if(y&(1ll<<i)) {y-=(1ll<<i); ret = ret*cur%P;}cur = cur*cur%P;}return ret;
}void initfact(int n)
{comb[0][0] = 1ll;for(int i=1; i<=n; i++) {comb[i][0] = comb[i][i] = 1ll; for(int j=1; j<i; j++) {comb[i][j] = (comb[i-1][j-1]+comb[i-1][j])%P;}}
}int getbitcnt(llong x)
{return bitcnt[x&524287]+bitcnt[(x>>19)&524287]+bitcnt[(x>>38)&524287];
}namespace Solve1
{void dfs(int pos,llong x){if(pos==sz) {ans[getbitcnt(x)]++; return;}dfs(pos+1,x); dfs(pos+1,x^a[b[pos]]);}
}namespace Solve2
{llong sta[mxM+3];llong f[mxM+3];void dfs(int pos,int cnt,llong x){if(pos==m) {f[cnt+getbitcnt(x)]++; return;}dfs(pos+1,cnt,x); dfs(pos+1,cnt+1,x^sta[pos]);}void solve(){for(int i=sz; i<m; i++){for(int j=0; j<sz; j++){if(a[b[j]]&(1ll<<b[i])) {sta[i] |= (1ll<<j);}}}dfs(sz,0,0ll);
//      for(int i=0; i<=m; i++) printf("%I64d ",f[i]); puts("");for(int k=0; k<=m; k++){for(int i=0; i<=m; i++){llong coe = 0ll;for(int j=0; j<=i&&j<=k; j++){llong tmp = comb[i][j]*comb[m-i][k-j]%P; if(j&1) {tmp = P-tmp;}coe+=tmp-P,coe+=(coe>>31)&P;}coe = coe*f[i]%P;ans[k]+=coe-P,ans[k]+=(ans[k]>>31)&P;}ans[k] = ans[k]*quickpow((P+1ll)/2ll,m-sz)%P;}}
}int main()
{initfact(mxM);for(int i=1; i<mxN; i++) bitcnt[i] = bitcnt[i>>1]+(i&1);scanf("%d%d",&n,&m);for(int i=1; i<=n; i++){llong x; scanf("%I64d",&x);for(int k=m-1; k>=0; k--) if(x&(1ll<<k)){if(!a[k]) {a[k] = x; sz++; break;}else {x ^= a[k];}}}for(int i=m-1; i>=0; i--) if(a[i]){for(int j=i+1; j<m; j++) if(a[j]&(1ll<<i)) {a[j] ^= a[i];}}
//  for(int i=0; i<m; i++) printf("%I64d ",a[i]); puts("");for(int i=0,j=0; i<sz; i++){while(!a[j]) {j++;} b[i] = j; j++;}for(int i=sz,j=0; i<m; i++){while(a[j]) {j++;} b[i] = j; j++;}if(sz<=26){Solve1::dfs(0,0ll);}else{Solve2::solve();}for(int i=0; i<=m; i++) ans[i] = ans[i]*quickpow(2ll,n-sz)%P;for(int i=0; i<=m; i++) printf("%I64d ",ans[i]); puts("");return 0;
}

Codeforces 1336E Chiori and Doll Picking (子集和变换、线性基、阈值算法、状压 DP、组合计数)...相关推荐

  1. Codeforces Gym 100676G Training Camp 状压dp

    http://codeforces.com/gym/100676 题目大意是告诉你要修n门课,每门课有一个权值w[i], 在第k天修该课程讲获得k*w[i]的学习点数,给出了课程与先修课程的关系,要修 ...

  2. Educational Codeforces Round 13 E. Another Sith Tournament 状压dp

    E. Another Sith Tournament 题目连接: http://www.codeforces.com/contest/678/problem/E Description The rul ...

  3. CodeForces - 1550E Stringforces(二分+状压dp)

    题目链接:点击查看 题目大意:给出一个长度为 nnn 的字符串,只包含前 kkk 个小写字母以及通配符 ???,现在可以将通配符替换成任意的前 kkk 个字母中的一个.设 f[i]f[i]f[i] 为 ...

  4. Codeforces Beta Round #8 C. Looking for Order 状压dp

    题目链接: http://codeforces.com/problemset/problem/8/C C. Looking for Order time limit per test:4 second ...

  5. CDOJ 1355 柱爷与三叉戟不得不说的故事(枚举子集状压dp)

    柱爷与三叉戟不得不说的故事 Time Limit: 500/500MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others) Subm ...

  6. BZOJ 2560: 串珠子 (状压DP+枚举子集补集+容斥)

    (Noip提高组及以下),有意者请联系Lydsy2012@163.com,仅限教师及家长用户. 2560: 串珠子 Time Limit: 10 Sec Memory Limit: 128 MB Su ...

  7. CodeForces - 1523D Love-Hate(随机数+状压dp)

    题目链接:点击查看 题目大意:给出 nnn 个 010101 序列表示二进制状态,问选择至少 ⌈n2⌉\lceil \frac{n}{2}\rceil⌈2n​⌉ 个状态进行位运算的与运算后得到的答案中 ...

  8. UVA11825 黑客的攻击 Hackers' Crackdown 状压DP,二进制,子集枚举

    题目链接Click Here [题目描述] 假如你是一个黑客,侵入了一个有着\(n\)台计算机(编号为\(1.2.3....n\))的网络.一共有\(n\)种服务,每台计算机都运行着所有服务.对于每台 ...

  9. Codeforces Round #585 (Div. 2) E. Marbles 状压dp + 逆序对

    传送门 文章目录 题意: 思路: 题意: 思路: 考虑数列最终的状态一定是相同颜色在一起,所以我们发现他的颜色是有顺序的!显然可以用状压dpdpdp来枚举颜色的顺序,但是又有问题了,你怎么确定当前这个 ...

最新文章

  1. linux创建进程读共享写复制,Linux下进程的创建、执行和终止
  2. bat输出log日志操作
  3. php将字符串转成json字符串数组,php数组怎么转成json字符串
  4. SEO -- 搜索引擎优化
  5. android系统三防机,这才是真正给老人设计的智能手机:三防+安卓系统+超大音量,AGM H2...
  6. apache 隐藏php版本,PHP+Apache环境中怎么隐藏Apache版本
  7. Android官方开发文档Training系列课程中文版:添加ActionBar之设置ActionBar
  8. H5页面适配iOS、Android和微信
  9. android socket 框架c#,C#与Android Socket通信
  10. 需求分析——识别系统需求中的三类事件
  11. SonarQube代码质量管理工具的安装(Linux)
  12. STM32驱动SG90舵机与HC_SR04超声波模块
  13. 助力公益数字化 火山引擎向公益机构捐赠多款技术产品
  14. 深度优先,Kruskal,Prim几种方式生成迷宫地图
  15. 张量的概念及基本运算
  16. 999.项目管理的一些计算技巧
  17. 一个简单的python-execl查重
  18. 银行排队信息预测系统数学建模
  19. ES(三)es查询语法
  20. 股票ctp交易接口是什么?

热门文章

  1. 云炬随笔20190301
  2. 云炬Android开发笔记 2-1项目初始化
  3. 退出python交互模式_python如何退出交互模式
  4. 小米8 twrp recovery_小米手机、红米手机通用刷机教程
  5. Redis介绍及常用应用场景介绍
  6. C#中代理的简单应用
  7. delphi中move函数的用法
  8. eventproxy
  9. 【unix时间戳小示例】linux/unix系统获取unix时间戳
  10. 一文看懂Python(九)-----可变参数函数