UOJ#310. 【UNR #2】黎明前的巧克力
给出 \(n\) 个数,从中选出两个互不相交的集合,使得第一个集合与第二个集合内的数的异或和相等。求总方案数,对 \(998244353\) 取模。\(n\leq 10^6,0\leq a_i\leq 10^6\)
如果两个集合的异或和相等,那么它们再异或一下即为 \(0\)。原问题转化为求选出一个异或和为 \(0\) 的集合并分为两个集合的方案数(去除两个集合都是空集的情况)。
设 \(f[i][j]\)表示前 \(i\) 个数中选出的数的异或和为 \(j\) 的方案数;
那么就有 \(f[i][j]=f[i−1][j]+2\times f[i−1][j\ {\rm xor}\ a[i]]\) ;
这是一个异或卷积的形式,相当于每次卷的是:\(b[0]=1,b[a[i]]=2\) ;
考虑对这个过程进行 FWT ,那么:
\(0\) 对每个位置的贡献都是 \(1\) ,即对应 \(f[i-1][j]\) 的贡献;
\(a[i]\) 对某些位置的贡献是 \(2\) (正的贡献) ,对某些位置的贡献是 \(-2\) (负的贡献)。
所以每次卷上的 \(b\) 数组的每个数都是 \(-1\) 或 \(3\) 。
和的FWT等于FWT的和。
因此把每个 \(a_i\) 对应的 \(b\) 数组求和后进行 FWT ,那么就知道了每个位置 FWT 的和;
最终再逆FWT回来即可。
时间复杂度 \(\mathcal{O}(nlogn)\) 。
how to 卡常:
FWT 过程中可以不取模;
最后不用逆 FWT :
正 FWT :\(a'_j=\sum\limits_i (−1)^{{\rm popcount}(i\&j) }a_i\)
设 FWT 的长度为 \(2^K\) ,我们观察到,如果我们把所有位置的的值加起来,下标为 \(0\) 的贡献永远是正的,其他下标 \(i\) 的贡献正好抵消 ( \(-1\) 和 \(+1\) 均为 \(2^{K-1}\) 种);所以我们只用把计算完贡献的所有位置加起来,然后 \(ans/=2^K\) 即可
int n,K,len,ans,mx,a[N],p[N];
inline int qpow(int a,int b) { R ret=1;
for(;b;b>>=1,a=1ll*a*a%M) if(b&1) ret=1ll*ret*a%M; return ret;
}
inline void cxor(int* a) {
for(R l=1;l<K;l<<=1)
for(R len=l<<1,i=0,x,y;i<K;i+=len)
for(R j=0;j<l;++j) {
x=a[i+j],y=a[i+j+l];
a[i+j]=x+y,a[i+j+l]=x-y;
}
}
inline void main() {
n=g(); for(R i=1,x;i<=n;++i)
x=g(),++a[x],mx=max(x,mx);
K=1; while(K<=mx) K<<=1;
p[0]=1; for(R i=1;i<=n;++i) p[i]=3ll*p[i-1]%M;
cxor(a);
//做完异或卷积后,我们就知道每个位置对应的 正的贡献 减 负的贡献 的值是多少辣
for(R i=0,x;i<K;++i) {
x=(a[i]+n)/2;
ans=(ans+p[x]*((n-x)&1?-1:1))%M;
}
printf("%d\n",(1ll*ans*qpow(K,M-2)%M-1+M)%M);
}
2020.04.18
原文地址:https://www.cnblogs.com/Jackpei/p/12726892.html
- Razor Engine,实现代码生成器的又一件利器
- 谈谈基于OAuth 2.0的第三方认证 [上篇]
- 我所理解的RESTful Web API [Web标准篇]
- ASP.NET Web API中的Controller
- iOS 转场动画探究(二)
- Swift 面向对象解析(二)
- 谈谈基于OAuth 2.0的第三方认证 [中篇]
- [ASP.NET Web API]如何Host定义在独立程序集中的Controller
- ASP.NET Web API自身对CORS的支持: EnableCorsAttribute特性背后的故事
- 【黑客解析】黑客是如何实现数据库勒索的 ?
- 直播回看:高可用架构入门 —— 腾讯云架构演变及经验
- 【腾讯云的1001种玩法】十分钟轻松搞定云架构之一 :从上云开始
- 【腾讯云的1001种玩法】十分钟轻松搞定云架构之二:更好的网络
- 【腾讯云的1001种玩法】十分钟轻松搞定云架构之三:更大的存储
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Spring Security 实战干货:UsernamePasswordAuthenticationFilter 源码分析
- 打卡群刷题总结0715——旋转链表
- 设计模式实战-中介模式,为你牵桥搭线
- 设计模式实战-迭代器模式,最常用的设计模式之一
- 设计模式实战-解释器模式,今天给你解疑答惑
- 时间不再浪费评估上!ThingJS 3D可视化开发不用愁
- 设计模式实战-命令模式
- 设计模式实战-责任链模式,超级实用
- 设计模式实战-代理模式,来看看主公如何托孤
- 设计模式实战-门面模式
- 设计模式实战-装饰器模式,教你怎么为代码添砖加瓦
- 设计模式实战-组合模式
- Hive如何实现自增序列
- 设计模式实战-过滤器模式,你总是这么挑三拣四
- 时间选择器组件之关于table走过的弯路