概述 & 前言

看到许多评价,说这次 CSP-J\texttt{CSP-J}CSP-J 的比赛题目质量甚至不如你谷的模拟赛,再加上 whk 实在落下太多了,所以就没打算补题。但是学校的老师非让我补不可,说要决定一下以后课程的安排。于是,就补了。于是,就 AK 了。

总体来讲,我感觉这次比赛的题目质量虽然不算很好,但也说的过去。除了第二题裸的一元二次方程差评外,其它的题目出的还是挺好的。(第一题直接 ABA^BAB 是不是有点过水?)

主观的难度评价(满分 555,相对与 PJ 其它题目来说)如下:

题目 思维难度 细节处理难度 代码复杂度
A. 乘方 1 1 1
B. 解密 1 1 1
C. 逻辑表达式 3 4 3
D. 上升点列 4 2 2

A. 乘方

题目链接:洛谷 P8813 [CSP-J 2022] 乘方

使用 暴力/快速幂 求 aba^bab 即可。值得一提的是,这里使用暴力并不会超时。因为最坏情况底数为 222 的话,也只需要乘 303030 次就会超过 10910^9109。但是实际运行下来,快速幂比暴力要快个几十毫秒,所以就贴快速幂的代码好了。

#include <iostream>
using LL = long long;
const LL MOD = 1e9;
LL n, m;
LL qpow(LL a, LL b) {LL ans = 1;for (; b; b >>= 1) {if (a > MOD) return -1;if (b & 1) {if (ans*a > MOD)return -1;ans = ans * a;}a *= a;}return ans;
}
int main() {scanf("%lld%lld", &n, &m);printf("%lld", qpow(n, m));return 0;
}

B. 解密

题目链接:P8814 [CSP-J 2022] 解密

题意太清晰了,一眼就能看出是一道数学题。

推导过程如下:
{n=p×q①e×d=(p−1)(q−1)+1②\begin{cases} n = p \times q \ \ ①\\ e \times d = (p-1)(q-1) + 1 \ \ ② \end{cases} {n=p×q  ①e×d=(p−1)(q−1)+1  ②​
化简 ②②② 式,得:
ed=pq−p−q+2③ed = pq - p - q + 2 \ \ ③ ed=pq−p−q+2  ③
将 ①①① 代入 ③③③ 中,得:
ed=n−p−q+2ed = n - p - q + 2 ed=n−p−q+2
变形后得:
p+q=n−ed+2p + q = n - ed + 2 p+q=n−ed+2
按照题目「数据范围」中的字母,我们将 n−ed+2n - ed + 2n−ed+2 替换为 mmm,即
p+q=m④p + q = m \ \ ④ p+q=m  ④
代入 ①①①:
p(m−p)=np(m-p) = n p(m−p)=n
展开并整理为关于 ppp 的一元二次方程:
p2−mp+n=0p^2 - mp + n = 0 p2−mp+n=0
这个方程有解,当且仅当 Δ\DeltaΔ 为完全平方数。即:
Δ=b2−4ac=m2−4n\Delta = b^2 - 4ac = m^2 - 4n Δ=b2−4ac=m2−4n
所以原方程的解为:
p=m±m2−4n2p = \frac{m\pm \sqrt{m^2 - 4n}}{2} p=2m±m2−4n​​
由于 p,qp,qp,q 必须要是整数,所以当 m±m2−4nm\pm \sqrt{m^2 - 4n}m±m2−4n​ 为奇数时也应该输出 NO

需要注意的是 nnn 的取值范围是 n≤1018n\leq 10^{18}n≤1018,注意开 long long

#include <iostream>
#include <cmath>
using LL = long long;
int T;
LL n, d, e;
int main() {scanf("%d", &T);while (T--) {scanf("%lld%lld%lld", &n, &d, &e);LL m = n + 2 - e*d;LL delta = m*m - 4*n;if (delta < 0) {puts("NO");continue;}LL x = sqrt(delta);if ((double)x!=sqrt(delta) or ((m-x)&1)) {puts("NO");continue;}printf("%lld %lld\n", (m-x)/2, (m+x)/2);}return 0;
}

C. 逻辑表达式

题目链接:洛谷 P8815 [CSP-J 2022] 逻辑表达式

这道题呢,说简单也不简单,说难呢也没啥难的,思路十分好想,但是实现起来有一定难度。

本题的思路很简单,[1,n][1,n][1,n] 的值,就是 [1,p−1][1,p-1][1,p−1] 的值与 [p+1,n][p+1,n][p+1,n] 的值运算后的结果,其中 ppp 为 [1,n][1,n][1,n] 括号外第一个逻辑运算符的下标。不难发现这就是一个递归的过程,所以直接模拟上述操作即可。

根据这个思路,我们不难设计出递归的参数:solve(l,r,c)solve(l,r,c)solve(l,r,c) 代表当前递归要计算 [l,r][l,r][l,r] 的值,并且以操作符 ccc 作为这一轮递归的分界点。

现在的问题是每一层递归中应该干什么事情。由于「或」的优先级比「与」低,所以我们应该先找到 [l,r][l,r][l,r] 中第一个或运算符的位置(为表示方便,下文将其用 pcp_cpc​ 代替),这样 [l,r][l,r][l,r] 就可以被分割为 [l,pc−1][l,p_c-1][l,pc​−1] 与 [pc+1,r][p_c+1,r][pc​+1,r] 这两个部分。由于找的是或运算符的位置,所以从 [l,pc−1][l,p_c-1][l,pc​−1] 中括号外的运算符一定全部为「与」。计算出 [l,pc−1][l,p_c-1][l,pc​−1] 的值(即 solve(l,pc−1,′&′)solve(l,p_c-1,'\&')solve(l,pc​−1,′&′) )即可。

这样描述实在是太抽象了,再加上我表达能力有限,可能一些原本会做的同学都被我整不会了。所以我画了几张图,可能会更清晰一点。同时,在模拟样例的过程中,我们还可以发现一些前面没有提到的细节。

这张图已经说明了一切。

这里再补充一点。由于每次我们要跳过括号内的内容,所以我们要知道每一个括号与谁配对。如果每次都遍历字符串来找括号的话,那时间复杂度为 O(N)\mathcal{O}(N)O(N),妥妥的超时。所以我们可以先预处理出与每个左括号配对的右括号的下标,然后用 O(1)\mathcal{O}(1)O(1) 的时间复杂度找到下标。

#include <iostream>
#include <cstring>
const int N = 1e6 + 9;
char a[N];
int n, cntAnd, cntOr, nxt[N];
int tp, stk[N];
// nxt[i] 表示第 i 个位置的左括号匹配的右括号所在的下标是几
int find(int pos, int r, char c) {while (a[pos]!=c and pos<=r)if (a[pos] == '(') {pos = nxt[pos] + 1;} else {pos++;}return pos;
}
int solve(int l, int r, char tgt = '|') {while (nxt[l] == r) l++, r--, tgt = '|';if (l == r) return a[l] == '1';int p = find(l, r, tgt);int res = solve(l, p-1, '&');for (int t; p < r; p = t) {t = find(p+1, r, tgt);if (a[p]=='&' and res==0) {cntAnd++;} else if (a[p]=='|' and res) {cntOr++;} else {res = solve(p+1, t-1);}}return res;
}
int main() {scanf("%s", a + 1);n = strlen(a+1);for (int i = 1; i <= n; i++)if (a[i] == '(') stk[++tp] = i;else if (a[i] == ')') nxt[stk[tp--]] = i;printf("%d\n", solve(1, n));printf("%d %d\n", cntAnd, cntOr);return 0;
}

D. 上升点列

题目链接:P8816 [CSP-J 2022] 上升点列

很显然是一道 DP 题。一开始我想到的是 DP 每个坐标,但是这样肯定不行(10910^9109),于是就想着先打骗分 DP。然后写到循环后发现我重复做了非常多重复的操作。只需要 DP 每个点就可以了。再看了一眼点数的数据范围,小的可怜。于是正解就这么想出来了。

n,kn,kn,k 的数据范围给我们了一个非常重要的提示,就是设计 DP 状态的时候可以依赖于这两个值。结合抄原题大法,很容易设计出 DP 状态:
fi,j表示以第 i个点结尾并且加 j个点能构成的序列的最大长度f_{i,j}\ 表示以第\ i\ 个点结尾并且加\ j\ 个点能构成的序列的最大长度 fi,j​ 表示以第 i 个点结尾并且加 j 个点能构成的序列的最大长度
然后就根据这个状态,设计一个状态转移方程:
fi,l+dis(i,j)−1=max{fj,l+dis(i,j)}f_{i, l+dis(i,j)-1} = max\{f_{j,l}+dis(i,j)\} fi,l+dis(i,j)−1​=max{fj,l​+dis(i,j)}
其中,lll 表示第 jjj 个点前加了 lll 个点

不要问我这个方程是怎么推出来的,问就是点这里

#include <iostream>
#include <algorithm>
const int N = 509, K = 109;
struct Node {int x, y;
} a[N];
int n, k, ans, dp[N][K];
// f[i][j] 表示以第 i 个点结尾并且加 j 个点能构成的序列的最大长度
int dis(int p1, int p2) { return abs(a[p1].x-a[p2].x)+abs(a[p1].y-a[p2].y); }
int main() {scanf("%d%d", &n, &k);for (int i = 1; i <= n; i++)scanf("%d%d", &a[i].x, &a[i].y);std::sort(a + 1, a + n + 1, [](const Node A, const Node B) {return A.x==B.x ? A.y<B.y : A.x<B.x;});for (int i = 1; i <= n; i++) { // 到第 i 个点dp[i][0] = 1;for (int j = 1; j < i; j++) // 接到第 j 个点后面if (a[j].y <= a[i].y)for (int l = 0; l+dis(i,j)-1 <= k; l++) { // 第 j 个点前加了 l 个点int t = l + dis(i, j) - 1;dp[i][t] = std::max(dp[i][t], dp[j][l] + dis(i, j));}}for (int i = 1; i <= n; i++)for (int j = 0; j <= k; j++)ans = std::max(ans, dp[i][j]+k-j);printf("%d", ans);return 0;
}

【题解】CSP2022-J第二轮题解相关推荐

  1. 【题解】CSP-J2021第二轮题解

    CSP-J2021第二轮题解 T1.分糖果 ⊗ \otimes ⊗ 简化题目:给定 l , r l,r l,r,求 max ⁡ i = l r ( i m o d n ) \max_{i=l}^{r} ...

  2. 【2021 CSP-J第二轮题解】

    一.分糖果 题意解析: 给定n,L,R,选取一个正整数k(L≤k≤R),使的k mod n的值ans最大,并输出ans. 根据取余运算的规律,可以得下图: 也就是说,L和R有两种不同的情况: L和R处 ...

  3. 2021年第十二届蓝桥杯省赛B组(C/C++)第二场题解

    文章目录 2021年第十二届蓝桥杯省赛B组(C/C++)第二场题解 1.求余 2.双阶乘 3.格点 4.整数分解 5.城邦 6.特殊年份 7.小平方 8.完全平方数 9.负载均衡 10.国际象棋 20 ...

  4. .net 遍历数组找重复值写入一个新数组_第二轮 Python 刷题笔记一:数组

    经过四十多天缓慢的刷题,现在进度大概是刷了八十多道 LeetCode 题,最近也在吸取过来人的经验,仍然需要对刷题计划进行调整. 首先明确一下目标,我是有些 Python 基础,想通过刷题掌握更多算法 ...

  5. NOIP历年第二轮入门组真题集合

    NOIP历年第二轮入门组真题集合 年份 题目 题解链接 2000 T1-计算器的改良 T2- 税收与补贴问题 T3-乘积最大 T4-单词接龙 题解链接 2001 T1-数的记数 T2-最大公约数和最小 ...

  6. 【百度之星2014~初赛(第二轮)解题报告】JZP Set

    声明 笔者近期意外的发现 笔者的个人站点 http://tiankonguse.com/ 的非常多文章被其他站点转载,可是转载时未声明文章来源或參考自 http://tiankonguse.com/  ...

  7. CSP-S 2019 第二轮 DAY2 简单解析(含部分分代码)

    CSP-S 2019第二轮第二试昨天上午正式结束了,赛后仔细拜读了DAY2的三个题目,难!但也是明年NOI选手不错的试炼机会,高分选手大概率也是明年NOI赛场上的选手. 第一题:Emiya 家今天的饭 ...

  8. 详解CSP-J/S第二轮认证

    CSP-J/S第二轮时间 CSP-J/S第二轮分为:CSP-J2和CSP-S2,必须先参加第一轮,达到一定的分数者方可参加第二轮.CSP-J/S第二轮在11月份第三个星期六和星期日进行. CSP-J/ ...

  9. 2019第十四届全国菌根学术研讨会(第二轮通知)

    文章目录 2019第十四届全国菌根学术研讨会(第二轮通知) 猜你喜欢 写在后面 2019第十四届全国菌根学术研讨会(第二轮通知) 菌根是植物与菌根真菌形成的互惠共生体,是土壤-微生物-植物的生命热区, ...

最新文章

  1. 解决使用Spring Boot、Multipartfile实现上传提示无法找到文件的问题
  2. Python基础概念_14_常见术语
  3. 腾讯云数据库2020年度盛典等你来
  4. 事务未提交 别人能读取到吗_Mysql 事务-面试笔记
  5. 同一个闭区间上有界变差函数的和与积都是有界变差函数
  6. 《大数据》2020年第6期目次摘要
  7. 在没有插件的情况下为Chrome设置Proxy
  8. [转]OpenMP 入门指南
  9. scala 高级十六 scala 集合和集合的高级特性 map flatten fllatmap zip reduce zip 等操作...
  10. 数字图像处理实验之对数变换
  11. 纪念愚人节微博禁止评论
  12. 线性代数 06 克莱默法则
  13. 关于微信小程序自定义导航栏时,如何获取手机状态栏和导航栏高度
  14. ventura 双系统win之间切换蓝牙设备自动连接教程
  15. 运营技巧|APP如何提升用户粘性与用户留存率
  16. 一文了解DCC-GARCH模型
  17. OATS-正交表测试策略
  18. 许愿墙HTML+CSS
  19. java实现ecc加密:通过AES生成公钥加密数据,ECC加密公钥
  20. SAP接口debug设置外部断点

热门文章

  1. 开源一个python的QQ频道机器人示例
  2. java-php-python-医院住院部信息管理系统计算机毕业设计
  3. OutputDebugString调试字符串输出及Delphi中调用显示最大字符长度限制为1024
  4. 即时通讯软件做到大组织架构秒更新的技术
  5. 北京物联展完美收官,拾联诠释“视频+物联网”新时代
  6. Vue.js获取返回数据中数组项个数
  7. 《PHP攻城狮面试宝典》
  8. Writeup of Android02(android) in WhaleCTF
  9. 【Leetcode_总结】538. 把二叉搜索树转换为累加树 - python
  10. 同时安装wore2003和word2007怎么把word设置为默认打开