模拟赛 21 题解

数论+计数+dp+贪心+堆

A.gcd

考虑到前缀 gcdgcd 值互不相同的只有 O(logn)O(\log n) 个,同时他们也是单调不升的。

所以我们可以暴力遍历所有的前缀 gcdgcd,用双向链表删去那些与前面值相同的元素。

在删的时候注意把数量累加就好了。

B.or_and

差一点想出做法

首先,可以分位考虑,考虑每一位被统计了多少次。

我们知道,二进制中的一位被统计,当且仅当这一位在两个数中至少有一个 11

我们可以统计出 [0,n][0,n] 的数中这一位是 11 的个数 NN[0,m][0,m] 中的个数 MM

那么简单容斥一下,这一位的贡献就是 Nm+MnNMNm+Mn-NM,我们重复计算了两位都是 11 的部分。

问题传化为了求 NNMM

分类讨论一下:

  • 如果当前这一位是 11,这一位前面的填法是唯一的,而后面可以按照原数填,也可以随便填。
  • 如果当前这一位是 00,我必须要把它变为 11,考虑从上面借一位,后面随便填。注意上面的方案数要加 11

C.middle

好题。

首先将 aa 数组排序,有如下性质:

  • aibia2nia_i\leqslant b_i\leqslant a_{2n-i},根据中位数的定义显然。
  • 任意 i<ji<j ,不存在 bj<bi<bj+1b_{j}<b_i<b_{j+1}bj+1<bi<bjb_{j+1}<b_i<b_j ,考虑中位数每次向外拓展两个单位,不会一下比两个数都小。

根据这两条性质,我们可以进行 dpdp

发现这些性质都是越向后越紧的,所以我们可以考虑从后向前 dpdp,维护哪些数可以成为中位数。

f[i][j][k]f[i][j][k] 表示已经确定了 [i,n][i,n],备选集合中 <bi<b_i 的数量为 jj>bi>b_i 的数量为 kk 的方案数。

考虑由 ii1i\rightarrow i-1,增加的两个数 ai1a_{i-1}amia_{m-i} (性质一),如果它们不等于 aia_i,那么备选集合将扩大。

我们转移的决策就是在枚举 bi1b_{i-1} 选什么。

  • 选了和 bib_i 相同的数:备选集合没有改变,直接 f[i][j][k]f[i1][x][y]f[i][j][k]\rightarrow f[i-1][x][y]
  • 选了小于 bib_i 的数,那么就枚举这个数在集合中的排名 ll。显然,排名在 [l+1,i][l+1,i] 之间的都没有用(性质二),而 bib_{i} 因为比 bi1b_{i-1} 大,归到了后面那类:f[i][j][k]f[i1][l][y+1]f[i][j][k]\rightarrow f[i-1][l][y+1]
  • 选了大于 bib_i 的数,同理:f[i][j][k]f[i1][l]f[i][j][k]\rightarrow f[i-1][l]

D.beautiful

保证前面的合法,考虑新加两个位置的贡献。

为了保证合法,最后一个位置肯定是右括号,我们来讨论前面填什么。

  • 填左括号,直接匹配。

  • 填右括号,为了合法,我们要把前面的一个右括号变为左括号,贪心地想,自然取代价最小的,即 ABA-B 最小。

所以开个小根堆,维护前面右括号中 ABA-B 的最小值即可。