序列奇偶

序列奇偶

题目描述:

有 nn 个数字,第 ii 个数字 viv_i 的范围在 [xi,yi][x_i,y_i] ,有 mm 个限制,第 ii 个限制要求 (∑i=lrvi) mod 2=s(\sum\limits_{i=l}^r v_i)\bmod 2=s 。

求有多少合法序列以及最小字典序合法序列。

n≤10,m≤40,0≤xi,yi≤109n\le 10,m\le 40,0\le x_i,y_i\le 10^9 。

暴力可以获得 10%10\% 的分数。

我们发现 mm 个条件都与  mod 2\bmod 2 有关,于是我们考虑之前确定每一个数字的奇偶性,并计算每一个数字为偶数的方案数 ai,0a_{i,0} ,奇数的方案数 ai,1a_{i,1} ,计算公式如下:

ai,1=⌊(yi−xi+1)+(xi mod 2)2⌋ai,0=(yi−xi+1)−ai,1\begin{aligned} a_{i,1}&=\lfloor\frac{(y_i-x_i+1)+(x_i\bmod 2)}{2}\rfloor\\ a_{i,0}&=(y_i-x_i+1)-a_{i,1} \end{aligned}

于是原问题被转化为一个 0101 序列,要求一段区间的异或值为定值,求方案数和转化为原序列之后的最小字典序序列。

直接枚举可以获得 50%50\% 的分数。

然后我们可以作一遍前缀异或和,记 Vi=(∑j=1ivj) mod 2V_i=(\sum\limits_{j=1}^i v_j)\bmod 2 。

然后限制条件就变为 Vli−1⊕Vri=siV_{l_i-1}\oplus V_{r_i}=s_i 。这个时候我们可以考虑将 li−1l_i-1 向 rir_i 连边权值为 sis_i 。之后用带权并查集维护 valival_i 表示 ii 和 ii 所在集合的根的奇偶性相同/不同。

带权并查集:

如果设 wiw_i 表示 ii 和并查集中 ii 的父亲 fif_i 的奇偶性的异或情况,那么 valival_i 应该为 ii 到根的边的异或值。

那么执行 getf\text{getf} 函数时,设当前 getf\text{getf} 的参数为 xx ,则应该有 vali=valfi⊕wival_i=val_{f_i}\oplus w_i 。时时刻刻维护这个值就行。

实际实现时可以偷懒,因为合并时必然是 xx 和 yy 之间直接执行 fy=xf_y=x ,所以我们可以把 ww 数组和 valval 数组合并为一个数组。

注意每次调用 valival_i 前要先用 getf\text{getf} ,不然可能使用的是一个未更新的值。

1
2
3
4
5
6
int getf(int x){
if(f[f[x]]==f[x])return f[x];
int t=getf(f[x]);
val[x]^=val[f[x]];
return f[x]=t;
}

然后是合并函数 add(x,y,s)\text{add(x,y,s)} 。

不妨设 x,yx,y 的根为 rtx,rtyrt_x,rt_y ,表示 xx 和 yy 的奇偶性的异或为 ss 。

首先如果说 rtxrt_x 和 rtyrt_y 不相等,此时只需要知晓 rtxrt_x 和 rtyrt_y 之间的关系就行。容易发现 wrty=s⊕valx⊕valyw_{rt_y}=s\oplus val_x\oplus val_y 。

然后就是 rtxrt_x 和 rtyrt_y 不相等。此时需要判断有没有矛盾出现。若 valx⊕valsval_x\oplus val_s 则没有矛盾,反之亦然。

1
2
3
4
5
6
7
8
9
10
11
12
void add(int x,int y,int S){
int X=getf(x),Y=getf(y);
if(X!=Y){
val[Y]=S^val[x]^val[y];
sz[X]+=sz[Y];
f[Y]=X;
}
else{
if(val[x]^val[y]^S)
flag=1;
}
}

此时如果出现了矛盾,可以直接判断出无解。

接着考虑如何计数。

注意到所有的点分为两类:

  • 没有点与这个点有关系,这是自由点。
  • 不是自由点,即连通块大小至少为 22 。

注意到第一种完全独立,很好处理;第二种连通块的个数不超过 n2\frac{n}{2} ,即 2020 。此时可以暴力枚举所有可能性,然后 DP 第一种即可。

具体的,设 fi,jf_{i,j} 表示前 ii 个点, Vi=jV_i=j 。则:

  • 若 ii 属于第一种,则枚举 kk ,有 fi−1,k×ai,j⊕k→fi,jf_{i-1,k}\times a_{i,j\oplus k}\to f_{i,j} 。
  • 否则,设 ii 必须选 jj ,则只能枚举 kk ,有 fi−1,k×ai,j⊕k→fi,jf_{i-1,k}\times a_{i,j\oplus k}\to f_{i,j} 。且 fi,j⊕1=0f_{i,j\oplus 1}=0 。

然后此时最终答案就是 fn,0+fn,1f_{n,0}+f_{n,1} ,边界条件 f0,0=1f_{0,0}=1 。

第一问就做完了。

第二问比较简单。你可以从前往后贪心选择,容易发现每个点只会有两个选择,即 xix_i 和 xi+1x_i+1 。

每次先选 xix_i ,然后使用带权并查集看是否有矛盾。如果有则 xix_i ,否则 xi+1x_i+1 。

这样就做完了。