洛谷 P7620 - CF1431J Zero-XOR Array(状压 dp)
首先显然题目等价于求有多少个长度 \(n-1\) 的序列 \(b\) 满足 \(a_i\le b_i\le a_{i+1}\),满足 \(b_1\oplus b_2\oplus\cdots\oplus b_{n-1}=a_1\oplus a_2\oplus\cdots\oplus a_n=S\)。
考虑入手解决这个问题,注意到 \(n\) 数据范围很小,只有 \(18\),而值域非常大,高达 \(2^{60}\),因此可以考虑拆位后 \(2^n\) 枚举个什么状态后计算。但是究竟枚举什么状态呢?我们不妨先来分析一些性质:
Observation 1. 对于某个 \(b_i\) 的第 \(j\) 位,总共有 \(3\) 种可能:
- \(b_i\) 的第 \(j\) 位到第 \(m-1\) 位(最高位)组成的前缀与 \(a_i\) 对应前缀相同
- \(b_i\) 的第 \(j\) 位到第 \(m-1\) 位组成的前缀不同于 \(a_i\),但与 \(a_{i+1}\) 相同
- \(b_i\) 的第 \(j\) 位到第 \(m-1\) 位组成的前缀既不同于 \(a_i\),也不同于 \(a_{i+1}\)
也就是将每个 \(b_i\) 的每一段前缀分为达到上界、达到下界和即每达到上界也没达到下界三种情况。
但是知道这个性质之后有什么用吗?
Observation 2. 对于某个 \(b_i\) 的某个 \(j\),如果它满足上面的第三种情况,并且我们已经固定了每个 \(b_i\) 第 \(j\) 位到第 \(m-1\) 位的取值,那么记 \(l_x\) 为 \(b_x\) 的后 \(j\) 位可以达到的最小值,\(r_x\) 为 \(b_x\) 的后 \(j\) 位可以达到的最大值,那么有 \(\prod\limits_{t\ne i}(r_t-l_t+1)\) 种合法的序列 \(\{b\}\)。
为什么?因为由于 \(b_i\) 即没有达到上界,也没有达到下界,因此 \(b_i\) 的后 \(j\) 位可以取遍 \([0,2^j)\) 中所有的值,因此对于任意一种其他位置后 \(j\) 位的填法都唯一存在一个 \(b_i\) 的后 \(j\) 位的填法,满足它们的异或和等于 \(S\)。
知道了这个性质之后,我们考虑枚举第一位存在某个 \(b_i\) 出现第三种情况的位置:第 \(j\) 位。那么对于第 \(j+1\) 位到第 \(m-1\) 位而言,每个 \(b_i\) 只有达到上界和达到下界两种可能,我们考虑再 \(2^n\) 枚举这个状态 \(st\),\(st\) 的第 \(i-1\) 位为 \(0\) 表示 \(b_i\) 的第 \(j+1\) 到 \(m-1\) 位达到下界,第 \(i-1\) 位为 \(1\) 表示 \(b_i\) 的第 \(j+1\) 到 \(m-1\) 位达到上界。
枚举这两个值之后,擅长解决计数问题的 \(dp\) 就要派上用场了,我们考虑记 \(dp_{i,0/1/2/3}\) 表示当前决策了前 \(i\) 个数的第 \(j\) 位的值,后面一维的定义如下:
- \(0\) 表示当前没有出现第三种情况,且该位异或和为 \(0\)
- \(1\) 表示当前没有出现第三种情况,且该位异或和为 \(1\)
- \(2\) 表示当前出现了第三种情况,且该位异或和为 \(0\)
- \(3\) 表示当前出现了第三种情况,且该位异或和为 \(1\)
转移就分这一位填 \(0\) 和这一位填 \(1\) 两种情况处理即可,具体来说:
- 如果 \(a_{i+1}\) 和 \(a_i\) 的第 \(j\) 位到第 \(m-1\) 位都相同,那么第 \(j\) 位只能填与 \(a_i\) 的第 \(j\) 位相同的值,方案数为 \(a_{i+1}-a_i+1\)
- 如果 \(a_{i+1}\) 和 \(a_i\) 的第 \(j+1\) 位到第 \(m-1\) 位都相同,但第 \(j\) 位不同,那么记 \(X=\lfloor\dfrac{a_{i+1}}{2^j}\rfloor\times 2^j\),\(b_i\) 第 \(j\) 位填 \(0\) 有 \(X-a_i\) 种可能,填 \(1\) 有 \(a_{i+1}-X+1\) 种可能,并且都不会出现情况 \(3\),随便转移一下即可。
- 否则如果 \(st\) 的第 \(i-1\) 位为 \(0\),则 \(b_i\) 的第 \(j+1\) 到 \(m-1\) 位与 \(a_i\) 相同,继续分情况讨论:
- 如果 \(a_i\) 的第 \(j\) 位为 \(1\),那么 \(b_i\) 的第 \(j\) 位只能填 \(1\),方案数为 \(\lfloor\dfrac{a_{i}}{2^j}\rfloor\times 2^j+2^j-a_i\),并且不会出现情况 \(3\)
- 如果 \(a_i\) 的第 \(j\) 位为 \(0\),那么 \(b_i\) 的第 \(j\) 位可 \(0\) 可 \(1\),填 \(0\) 的方案数依旧是 \(\lfloor\dfrac{a_{i}}{2^j}\rfloor\times 2^j+2^j-a_i\),填 \(1\) 的方案数则是 \(2^j\),并且会出现情况 \(3\)。
- 如果 \(st\) 的第 \(i-1\) 位为 \(1\),与 \(st\) 的第 \(i-1\) 位为 \(0\) 的情况类似,镜像一下即可。
最终累加入答案的值即为 \(dp_{n-1,2+d}\),其中 \(d\) 为 \(S\) 第 \(j\) 位的值。
时间复杂度 \(2^n·nm\)
const int MAXN=17;
const int MOD=998244353;
int n,m,ans=0,dif[MAXN+5];ll l[MAXN+5],r[MAXN+5],sum=0;
bool check(int st,int k){
ll ss=0;
for(int i=1;i<n;i++){
if(st>>(i-1)&1){
if(dif[i]<k) return 0;
ss^=r[i];
} else ss^=l[i];
} return (ss>>k)==(sum>>k);
}
int dp[MAXN+3][4];
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%lld",&l[i]),r[i-1]=l[i],sum^=l[i];
for(int i=1;i<n;i++){
dif[i]=-1;
for(int j=m-1;~j;j--) if((l[i]>>j&1)^(r[i]>>j&1)){
dif[i]=j;break;
}
}
for(int i=0;i<(1<<n-1);i++) if(check(i,0)) ans++;
for(int i=0;i<m;i++) for(int j=0;j<(1<<n-1);j++) if(check(j,i+1)){
memset(dp,0,sizeof(dp));dp[0][0]=1;
for(int p=1;p<n;p++){
if(dif[p]<i){
int d=l[p]>>i&1,num=(r[p]-l[p]+1)%MOD;
for(int t=0;t<4;t++) dp[p][t]=(dp[p][t]+1ll*dp[p-1][t^d]*num)%MOD;
} else if(dif[p]==i){
ll lim=l[p]|((1ll<<i)-1);int num0=(lim-l[p]+1)%MOD,num1=(r[p]-lim)%MOD;
for(int t=0;t<4;t++){
dp[p][t]=(dp[p][t]+1ll*dp[p-1][t]*num0)%MOD;
dp[p][t]=(dp[p][t]+1ll*dp[p-1][t^1]*num1)%MOD;
}
} else if(j>>(p-1)&1){
if(r[p]>>i&1){
ll lim=r[p]>>i<<i;
int num0=(1ll<<i)%MOD,num1=(r[p]-lim+1)%MOD;
for(int t=0;t<4;t++) dp[p][t]=(dp[p][t]+1ll*dp[p-1][t^1]*num1)%MOD;
for(int t=2;t<4;t++) dp[p][t]=(0ll+dp[p][t]+1ll*num0*dp[p-1][t]+dp[p-1][t&1])%MOD;
} else {
ll lim=r[p]>>i<<i;
int num0=(r[p]-lim+1)%MOD;
for(int t=0;t<4;t++) dp[p][t]=(dp[p][t]+1ll*dp[p-1][t]*num0)%MOD;
}
} else {
if(~l[p]>>i&1){
ll lim=l[p]|((1ll<<i)-1);
int num0=(lim-l[p]+1)%MOD,num1=(1ll<<i)%MOD;
for(int t=0;t<4;t++) dp[p][t]=(dp[p][t]+1ll*dp[p-1][t]*num0)%MOD;
for(int t=2;t<4;t++) dp[p][t]=(0ll+dp[p][t]+1ll*num1*dp[p-1][t^1]+dp[p-1][(t^1)&1])%MOD;
} else {
ll lim=l[p]|((1ll<<i)-1);
int num1=(lim-l[p]+1)%MOD;
for(int t=0;t<4;t++) dp[p][t]=(dp[p][t]+1ll*dp[p-1][t^1]*num1)%MOD;
}
}
}
int d=sum>>i&1;
ans=(ans+dp[n-1][2|d])%MOD;
} printf("%d\n",ans);
return 0;
}
洛谷 P7620 - CF1431J Zero-XOR Array(状压 dp)的更多相关文章
- 【题解】洛谷P2704 [NOI2001] 炮兵阵地(状压DP)
洛谷P2704:https://www.luogu.org/problemnew/show/P2704 思路 这道题一开始以为是什么基于状压的高端算法 没想到只是一道加了一行状态判断的状压DP而已 与 ...
- 【题解】洛谷P1896 [SCOI2005] 互不侵犯(状压DP)
洛谷P1896:https://www.luogu.org/problemnew/show/P1896 前言 这是一道状压DP的经典题 原来已经做过了 但是快要NOIP 复习一波 关于一些位运算的知识 ...
- 洛谷P1171 售货员的难题【状压DP】
题目描述 某乡有n个村庄(1 输入格式: 村庄数n和各村之间的路程(均是整数). 输出格式: 最短的路程. 输入样例: 3 0 2 1 1 0 2 2 1 0 输出样例 3 说明 输入解释 3 {村庄 ...
- 2018.07.18 洛谷P1171 售货员的难题(状压dp)
传送门 感觉是一道经典的状压dp,随便写了一发卡了卡常数开了个O(2)" role="presentation" style="position: relati ...
- 洛谷P2761 软件补丁问题(状压dp)
传送门 啊咧……这题不是网络流二十四题么……为啥是个状压dp…… 把每一个漏洞看成一个状态,直接硬上状压dp 然后因为有后效型,得用spfa //minamoto #include<iostre ...
- 洛谷$P3226\ [HNOI2012]$集合选数 状压$dp$
正解:$dp$ 解题报告: 传送门$QwQ$ 考虑列一个横坐标为比值为2的等比数列,纵坐标为比值为3的等比数列的表格.发现每个数要选就等价于它的上下左右不能选. 于是就是个状压$dp$板子了$QwQ$ ...
- 洛谷 P2622 关灯问题II【状压DP】
传送门:https://www.luogu.org/problemnew/show/P2622 题面: 题目描述 现有n盏灯,以及m个按钮.每个按钮可以同时控制这n盏灯--按下了第i个按钮,对于所有的 ...
- UOJ #129 / BZOJ 4197 / 洛谷 P2150 - [NOI2015]寿司晚宴 (状压dp+数论+容斥)
题面传送门 题意: 你有一个集合 \(S={2,3,\dots,n}\) 你要选择两个集合 \(A\) 和 \(B\),满足: \(A \subseteq S\),\(B \subseteq S\), ...
- 洛谷 P6499 - [COCI2016-2017#2] Burza(状压 dp)
题面传送门 一道挺有意思的思维题(?) 首先我们假设根节点深度为 \(0\),那么 Daniel 的目标显然就是堵住一些节点使得 Stjepan 不能移动到深度为 \(k\) 的节点,Stjepan ...
- 【题解】洛谷P1879 [USACO06NOV] Corn Fields(状压DP)
洛谷P1879:https://www.luogu.org/problemnew/show/P1879 思路 把题目翻译成人话 在n*m的棋盘 每个格子不是0就是1 1表示可以种 0表示不能种 相邻的 ...
随机推荐
- 想要彻底搞懂大厂是如何实现Redis高可用的?看这篇文章就够了!(1.2W字,建议收藏)
高可用HA(High Availability)是分布式系统架构设计中必须考虑的因素之一,它通常是指,通过设计减少系统不能提供服务的时间. 假设系统一直能够提供服务,我们说系统的可用性是100%.如果 ...
- DevOps 时代的高效测试之路
10 月 22 日,2021 届 DevOps 国际峰会在北京顺利召开,来自国内外的顶级技术专家共同畅谈 DevOps 体系与方法.过程与实践.工具与技术.CODING 测试及研发流程管理产品总监程胜 ...
- 混合开发框架Flutter
Flutter开发简介与其他的混合开发的对比 为什么要使用Flutter? 跨平台技术简介 Hybrid技术简介 QT简介 Flutter简介 为什么要使用Flutter? Flutter有什么优势? ...
- OO面向对象第三次作业总结
面向对象第三次作业总结 一.JML基础梳理及工具链 注释结构 行注释://@annotation 块注释:/*@ annotation @*/ 两种注释都是放在被注释部分上面. 常见表达式 原子表达式 ...
- 你知道如何从单片机过渡到嵌入式linux需要经历那些吗?(这个亲身体验有效)
就现在的行业发展来看只会单片机已经不吃香了并且在薪资待遇方面来看的话单片机的收入限制性太强可能工作很多年之后发现没有了成长空间,因此逐渐转到嵌入式Linux这个方向是越来越多的人的一个选择,那么接触了 ...
- Taylor公式原来可以这么简单
1.Taylor公式 解决:含有高阶导数的中值定理或定积分.极限运算等题目 条件:f(x)在x=x0领域内(n+1)阶可导 结论:f(x)=Pn(x)+Rn(x) 2.x和x0的取值 3.Taylor ...
- ASP.NET MVC 中使用 jQuery 实现异步搜索功能
常见的几种异步请求方式: Ajax.BeginForm 异步提交文本的形式 Ajax.ActionLinkk 文本链接的形式 Client Validataion 客户端的认证 一.用jQuer ...
- reorder-list leetcode C++
Given a singly linked list L: L 0→L 1→-→L n-1→L n, reorder it to: L 0→L n →L 1→L n-1→L 2→L n-2→- You ...
- Markdown使用方式
区块 区块引用在段落开头使用>,后面紧跟一个空格符号 > 区块引用 > XXX > XXX 高级技巧 HTML元素 居中 <center>XXX</cent ...
- Centos 7 端口聚合
简单粗暴,直接复制命令就好了 还是先啰嗦一下,添加网卡之后,如果没有网卡配置文件,可以通过nmcli con show 先查看网卡的唯一ID,然后复制其他的网卡配置文件,修改device项,name项 ...