abc150
题解翻译器 2022-4-27
A题
过于简单,不解
B题
过于简单,不解
C题
solve1
简单来讲,暴力去 d f s dfs dfs 找到全排列同时标记当前是第几个排列即可。
solve2
康托展开即可
具体实现是从前往后以此扫描,假设总共有 n n n 个数,当前点是 a i a_i ai,只需要统计有多少个 a j ( j > i ) a_j(j > i) aj(j>i) 满足 a i > a j a_i > a_j ai>aj,假设有 m i m_i mi 个,则贡献加上 m i ∗ ( n − i ) ! m_i * (n-i)! mi∗(n−i)!,每一个的排列就是序号就是 ∑ m i ∗ ( n − i ) ! \sum m_i*(n-i)! ∑mi∗(n−i)!。这个序号是从 0 0 0 开始的。
D题
给定长度为 n n n 的序列 { a i } \lbrace a_i \rbrace {ai}, a i a_i ai 都是偶数,问 1 1 1 到 M M M 中有多少个 X X X 满足:对于所有的 i i i,都存在非负整数 p i p_i pi 使得 X = a i ∗ ( p i + 0.5 ) X = a_i*(p_i + 0.5) X=ai∗(pi+0.5)。
M M M 过大,我们只能考虑这样的 X X X 是否满足某些特征,我们尝试构造 X X X,我们尝试拆开式子,实际上述要求等价于 X = a i 2 ∗ ( 2 k + 1 ) X= \frac{a_i}{2}*(2k+1) X=2ai∗(2k+1),也就是说我们要求的 X X X 实际上是 { a i 2 } \lbrace \frac{a_i}{2} \rbrace {2ai} 的公倍数,且对于每一个 a i 2 \frac{a_i}{2} 2ai ,倍数都是奇数。那么显然存在一个最小公倍数,我们只需要检验最小公倍数是否是所有数的奇数倍即可。我们假设得到的数为 X 0 X_0 X0,那么所有的奇数倍的 X 0 X_0 X0 也都是答案。
E题
由于要计算每个 2 n × 2 n 2^n \times 2^n 2n×2n 个 01 01 01 串的比较情况。显然实际上存在很多类似的情况,我们定义 P i P_i Pi 为十进制表示为 i i i 的二进制串,如果是 P i P_i Pi 和 P j P_j Pj 为一组,显然我们可以把 P i ⨂ P i P_i \bigotimes P_i Pi⨂Pi , P j ⨂ P i P_j \bigotimes P_i Pj⨂Pi ,这样与上述的情况实际是等价的,那么实际上我们只需要得到 P 0 P_0 P0 与 P j , j ∈ ( 0 , 2 n ) P_j ,j \in (0,2^n) Pj,j∈(0,2n) 的总贡献即可。最后乘以 2 n 2^n 2n 即是答案。
首先讨论一个问题,什么情况 P 0 P_0 P0 与 P j P_j Pj 会最优,我们考虑每一个 1 1 1 的位置,把对应的 C i C_i Ci 提取出来记做 c i c_i ci,显然先消去最小的,最后的贡献会最小(大的数被计算的越少越好)。那么假设我们按照了 C C C 从大到小排好了序,实际上就是计算 ∑ 1 m c i ∗ i \sum _1 ^m c_i * i ∑1mci∗i,这里的 m m m 是指 1 1 1 的个数。
我们显然不能讨论每个位置是否会出现 1 1 1,这样的情况还是太多了,我们需要考虑如果整合这些值,一个可行的方法是,我们考虑每一个 C i C_i Ci 的贡献,首先按照 C C C 从大到小排序,我们去枚举 C i C_i Ci 在串中的 1 1 1 排名第 j j j 的情况,我们记 f ( i , j ) f(i,j) f(i,j) 为 i i i 是第 j j j 个 1 1 1 的情况总数,那么对于 i i i 的贡献就是 C i ∗ ∑ ( f ( i , j ) ∗ j ) C_i*\sum (f(i,j)*j) Ci∗∑(f(i,j)∗j)。
我们考虑 f ( i , j ) f(i,j) f(i,j) 是多少,实际上很容易得到 f ( i , j ) = ( i − 1 j − 1 ) ∗ 2 n − i f(i,j) = { {i-1} \choose {j-1} } * 2^{n-i} f(i,j)=(j−1i−1)∗2n−i,解释是 i i i 的前面出现 j − 1 j-1 j−1 个 1 1 1,后面任意即可。一个简单的组合数学问题。
要是我们直接去计算,复杂度是 O ( n 2 ) O(n^2) O(n2),组合数需要预处理(线性组合数)。
我们考虑如果快速得到
∑
f
(
i
,
j
)
∗
j
\sum f(i,j)*j
∑f(i,j)∗j
∑
1
i
f
(
i
,
j
)
∗
j
=
2
n
−
i
∑
1
i
(
i
−
1
j
−
1
)
∗
j
=
2
n
−
i
∑
0
i
−
1
(
i
−
1
j
)
∗
(
j
+
1
)
=
2
n
−
i
∑
0
i
−
1
(
i
−
1
j
)
∗
j
+
2
n
−
i
∑
0
i
−
1
(
i
−
1
j
)
=
2
n
−
i
(
(
i
−
1
)
∗
2
i
−
2
+
2
i
−
1
)
\begin{aligned} \sum _1 ^i f(i,j)*j &= 2 ^{n-i}\sum_1^i {i-1 \choose j-1} * j \\ &= 2 ^{n-i} \sum_0 ^{i-1} {i-1 \choose j} * (j + 1) \\ &= 2 ^{n-i} \sum_0 ^{i-1} {i-1 \choose j} * j + 2 ^{n-i} \sum_0 ^{i-1} {i-1 \choose j} \\ &= 2 ^{n-i} ((i - 1) * 2 ^{i-2} + 2 ^{i-1}) \end{aligned}
1∑if(i,j)∗j=2n−i1∑i(j−1i−1)∗j=2n−i0∑i−1(ji−1)∗(j+1)=2n−i0∑i−1(ji−1)∗j+2n−i0∑i−1(ji−1)=2n−i((i−1)∗2i−2+2i−1)
第三到第四步是一个经典的公式:
∑
0
n
(
n
i
)
∗
i
=
n
∗
2
n
−
1
\sum _0 ^{n} {n \choose i} * i = n * 2^{n-1}
0∑n(in)∗i=n∗2n−1
结果就是
2
n
∑
1
n
2
n
−
i
C
i
(
(
i
−
1
)
∗
2
i
−
2
+
2
i
−
1
)
2^n \sum _1 ^n 2 ^{n-i} C_i((i - 1) * 2 ^{i-2} + 2 ^{i-1})
2n1∑n2n−iCi((i−1)∗2i−2+2i−1)
那么这个问题就优化到了 O ( n ) O(n) O(n),官方题解有一种 O ( n log n ) O(n \log n) O(nlogn) 的做法,有兴趣可以看。
E题
solve1
枚举偏移量, 随机取值去判断,wa在了一个点。
solve2
tag: 异或也具有差分性,就像减法一样。简单证明一下就可以知道。
证明:
a i , a i + 1 a_i,a_{i+1} ai,ai+1 异或 k k k 变成 b i , b i + 1 b_i,b_{i+1} bi,bi+1,当且仅当 a i ⨂ a i + 1 = b i ⨂ b i + 1 a_i \bigotimes a_{i+1} = b_i \bigotimes b_{i+1} ai⨂ai+1=bi⨂bi+1 时存在唯一 k k k。可以类比减法。
a i ⨂ k = b i a i + 1 ⨂ k = b i + 1 ( a i ⨂ k ) ⨂ ( a i + 1 ⨂ k ) = a i ⨂ a i + 1 \begin{aligned} a_i \bigotimes k &= b_i \\ a_{i+1} \bigotimes k &= b_{i+1} \\ (a_i \bigotimes k) \bigotimes (a_{i+1} \bigotimes k) &= a_i \bigotimes a_{i+1} \end{aligned} ai⨂kai+1⨂k(ai⨂k)⨂(ai+1⨂k)=bi=bi+1=ai⨂ai+1
如果异或值不相等,则必然不存在 k k k。如果相等,那么设 k 0 = a i ⨂ b i k_0 = a_i \bigotimes b_i k0=ai⨂bi ,可以知道 a i + 1 ⨂ k 0 = b i + 1 a_{i+1} \bigotimes k_0 = b_{i+1} ai+1⨂k0=bi+1。
故得证。
那么如果我们得到两个数列的差分值,做 K M P KMP KMP 匹配就好。如果不是异或,是减法也一样。