CSP-J 2022
CSP-J 2022 总结
T1 乘方
思路
首先,不看数据范围,可以知道最简单的方法就是从 \(1\) 到 \(b\) 循环一遍,求出 \(a ^ b\)。
但是,现在有一个问题,\(b\) 太大了!
那该怎么办呢?
如果你仔细观察的话,就会发现题目有一个条件:如果大于 \(10 ^ 9\) 就输出 -1。
这说明了什么?
你知道 \(2 ^ {31} = 2147483648\),是 \(\ge 10 ^ 9\) 的,而你又知道对于同一个数,它 \(\log_2\) 得到的结果肯定要大于 它 \(\log_x\) \((x > 2)\) 的,那么如果加上判断是否大于 \(10 ^ 9\) 这个条件的话,循环最多执行 \(31\) 次。
但是,这里还要考虑一个事情,如果 \(a = 1, b = 10 ^ 9\) 呢?\(1\) 的任何次方都是 \(1\),还是会执行 \(10 ^ 9\) 次,所以需要特殊判断一下这种情况。
T2 解密
思路
70 分
首先,题目很明显告诉了我们一个公式:\(n = p \times q\),这就说明,\(p\) 和 \(q\) 都得是 \(n\) 的因数,那么可以直接找约数,再判断是否满足条件。这样,你就拿到了宝贵的 60 分。
如果你是个爱仔细观察数据的同学,你就会发现,第 7 个数据点保证 \(q = p\),直接特殊判断即可。
100 分
如果仔细观察数据范围的话,你会看到题目给了一个貌似没有什么用的 \(m\),\(m = n - e \times d + 2\)。
那么,就可以考虑从 \(m\) 下手。
首先,我们知道 \(e \times d = (p - 1) \times (q - 1) + 1\),化简后也就是 \(e \times d = pq - p - q + 1 + 1\)。
那么 \(m = n - e \times d + 2 = n - (pq - p - q + 1 + 1) + 2 = n - pq + p + q - 2 + 2\)。
而 \(n = p \times q\),所以 \(m = n - pq + p + q - 2 + 2 = p + q\)。
紧接着,我们应该都知道 “和一定,差小积大”,也就是当和是一个定值的时候,两个数的差越小,乘积就越大。
而在这里,你又知道 \(m\) 就是 \(p\) 和 \(q\) 的和,而乘积会随着它们的差变小而越变越大,所以,你会神奇的发现,这道题有单调性!!!
那么,就可以请二分登场了。
这个事情就变得很简单了,二分 \(p\),判断乘积是大于 \(n\) 还是小于 \(n\),最后判断并输出即可。
其实还有一种解方程的解法,只是我不会。
T3 逻辑表达式
思路
首先,我们得知道,逻辑表达式实际上只有 2 种运算符 (&, |)
,但是因为 ()
的加入,使得这个运算变得更加复杂了。
所以,题目温馨的给出了没有 ()
的数据,我们就先处理这种情况。
首先,我们知道 &
的运算优先级是大于 |
的,所以其实可以简单的将 |
看作 +
,&
看作 *
,这就对应到了洛谷上的另一道题,P1981。
其实就是用栈来模拟,当碰到 &
时,就运行栈顶的所有 |
运算符。
那么,()
到底会影响到什么呢?
我们都知道,在 ()
内的所有运算,都是优先于 ()
外的运算的,所以,()
影响的其实是 优先级。
那么我们就可以将 &
的优先级定为 1,|
的优先级定为 0。
而这里,有两种优先级,所以我们可以在每一层括号中,将所有运算符的优先级都加上 2,当脱离出这一层括号时,就减少 2。
所以可以用一个基础值来记录经过了多少个括号,然后对于每一个运算符,直接用基础值加上原本的运算符优先级就可以了。
那么短路次数又应该怎么计算呢?
其实也很简单,只要在每次运算的时候进行计算就可以了。
如果当前不发生短路,就直接将两个运算数带着的短路次数进行相加即可,否则,就只留下前面运算数的短路次数,并且加上这次短路即可。