Codeforces Round 940 (Div. 2)
A. Stickogon
思路:
- 题目要求每条边只能有一个木棍,然后我们可以联想到最小的正多边形是正三角形,所以只需要将每种木棍的个数存起来,然后求可以组成多少个正三角形即可
时间复杂度:\(O(n)\)
1 | void solve() { |
B. A BIT of a Construction
思路:
- 有一个关于位运算的前置知识,将一个
int
范围里的每一位都置为1
可以这样操作(1 << 31) - 1
,那么我们将一个小于x
的最大数的每一位置为1
就是(1 << __lg(x)) - 1
,所以我们只需要把小于等于k
的最大那个二进制下1
最多的那个数求出来即可,然后输出k - x
和n - 2
个0
。
时间复杂度:\(O(n)\)
1 | void solve() { |
C. How Does the Rook Move?
题目大意:每次玩家可以选择一个位置 \((r_i, c_i)\) 然后机器人会在镜像位置 \((c_i, r_i)\) 也放一个棋子,如果玩家在对角线上放一个棋子 \((i, i)\) ,那么机器人不会操作,然后题目要求给你一个残局,问有多少种满足 \(N\) 皇后问题的解 \(\rightarrow\) 每行每列都只存在一个棋子
思路:
- 我们可以发现,每当我们在非对角线的位置 \((r_i, c_i)\)
下一个任意颜色的棋子时,机器人在镜像位置 \((c_i, r_i)\)
也会下一个棋子,那么我们将丢失
2
行和2
列,如果在对角线位置下一个棋子,我们只会丢失1
行1
列。 - 我们用分治的思想考虑,每次下一个棋子,这一个或者两个棋子,会把棋盘分割为
1
个或者4
个小的棋盘,棋盘的大小不重要,重要的在于,大的棋盘会变成更小的棋盘,而且被分割出的棋盘一定是一个边长为k
的正方形,所以问题就变成了求一个边长为k
的棋盘上的n
皇后问题。- 对于一个边长为
1
的正方形棋盘,它的方案数为1
,一个边长为2
的棋盘,它的方案数为3
,我们可以发现,一个边长为x
的棋盘,它的方案数由一个边长为x - 1
的棋盘继承而来。 - 对于我们下一步棋,我们如果下在对角线,那么会损失
1
行和1
列,会产生一个k - 1
阶的新棋盘,然后在这个新的棋盘中,其方案数为 \(1 \times dp[k - 1]\) - 如果我不下在对角线处,就会损失
2
行2
列,那么我们有 \(2 \times (k - 1)\) 种下棋方案,剩下k - 2
阶的棋盘,那么在一个k - 2
阶的棋盘里,它的方案数为 \(2 \times (k - 1) \times dp[k - 2]\)
- 对于一个边长为
- 所以,对于一个
N
阶的棋盘,它的方案数为 \(dp[k] = dp[k - 1] + 2 \times (k - 1) \times dp[k - 2]\)
时间复杂度:\(O(N)\)
如果实在不理解,可以看看这个图文讲解
1 | constexpr int N = 3E5 + 10, P = 1E9 + 7; |
D. A BIT of an Inequality
思路:
- 可以把题目的式子变形一下 \(f(x, y) \space \oplus \space f(y, z) > f(x, z)\)
- 根据题目给的 \(n\) 的范围(\(10^5\)),这题就一定不是枚举,不然就是 \(O(n^3)\),铁定超时。要做到 \(O(1)\) 的时间查询,那么我们可以采用异或前缀和
- 我们根据异或前缀和的思路,把式子变形一下 \(f(x, y) \space \oplus \space f(y, z) > f(x, z) \Rightarrow (S_z - S_{x - 1}) \space \oplus \space a_y > (S_z - S_{x - 1})\),那么我们可以明确的知道,这个式子左边多异或的那个 \(a_y\) 它可以使得整个式子变大,然后我们考虑,在一个数什么情况下,它异或另一个数,可以使得结果变大,一定是这个 \(a_y\) 的最高位是 \(1\),然后我们可以按这个思路,设数组 \(bit[i][j]\) 表示第 \(i\) 位前缀和 \(1\) 的个数,利用乘法原理,进行计算有多少个三元组满足条件。
时间复杂度:\(O(30 \times n)\)
1 | void solve() { |