当前位置: 首页 > news >正文

新生赛 F,H,J 题解

F. 金苹果

搜索题。

首先在输入中记录点 \(S,P,T\) 的坐标。

第一问,搜索要求不经过点 \(P\),可以将 px,py 记录成 #,然后从 \(S\) 开始搜(dfs 或 bfs 均可)能不能到达 \(T\)

第二问,从 \(S\) 出发能否先经过 \(P\) 再到达 \(T\),就相当于能否从 \(P\) 出发,既能到达\(S\)又能到达\(T\),两次搜索判断即可。

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int inf = 50 + 7;
int n, m;
char s[inf][inf];
int dx[4] = {0, 0, 1, -1},dy[4] = {1, -1, 0, 0};
bool vis[inf][inf];
bool dfs(int x, int y, char ed)
{if (s[x][y] == ed){return 1;}vis[x][y] = 1;bool ret = 0;for (int i = 0; i < 4; i++){int xx = x + dx[i], yy = y + dy[i];if (xx < 1 || xx > n || yy < 1 || yy > m)continue;if (vis[xx][yy] || s[xx][yy] == '#')continue;ret = ret || dfs(xx, yy, ed);if (ret)return ret;}return ret;
}
struct node
{int x, y;node() {}node(int x, int y) : x(x), y(y) {}
};
void _()
{cin >> n >> m;for (int i = 1; i <= n; i++){cin >> (s[i] + 1);}int sx, sy, px, py, tx, ty;for (int i = 1; i <= n; i++){for (int j = 1; j <= m; j++){if (s[i][j] == 'S')sx = i, sy = j;if (s[i][j] == 'P')px = i, py = j;if (s[i][j] == 'T')tx = i, ty = j;}}memset(vis, 0, sizeof(vis));s[px][py] = '#';cout << (dfs(sx, sy, 'T') ? "Yes" : "No") << ' ';s[px][py] = 'P';memset(vis, 0, sizeof(vis));bool rchS = dfs(px, py, 'S');memset(vis, 0, sizeof(vis));bool rchT = dfs(px, py, 'T');cout << ((rchS && rchT) ? "Yes" : "No") << '\n';
}
signed main()
{int qwq = 1;cin >> qwq;for (int i = 1; i <= qwq; i++)_();return 0;
}

H. 简单点

对于两个数之间的运算,第一反应是乘法得到的结果会比加法大。但是会有一种特殊情况,即两个运算数中存在 \(1\),此时 \(a + 1 > a * 1\)

于是我们将找出所有的 \(1\),进行加操作,找出所有 \(>1\) 的数,进行乘操作,然后两者结果相乘即可。

但是仔细观察会发现,如果只有一个 \(1\),那么这时候需要将这个 \(1\) 先和 \(>1\)最小数字 相加后再相乘,因为 \(a * b * c + 1 < a * (b + 1) * c <(a + 1) * b * c\)

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int inf = 1e5 + 7, mod = 998244353;
int n, sum1, ans;
vector<int> a;
signed main()
{cin >> n;for (int i = 1; i <= n; i++){int k;cin >> k;if (k == 1)sum1++;elsea.push_back(k);}sort(a.begin(), a.end());if (sum1 == 1){ans = sum1 + a[0];for (int i = 1; i < a.size(); i++)ans = ans * a[i] % mod;}else{ans = 1;if (sum1)a.push_back(sum1);for (int i = 0; i < a.size(); i++)ans = ans * a[i] % mod;}cout << ans << '\n';return 0;
}

由于取模的特性,在乘的过程中可能重新得到1,此时应该进行乘操作,但是如果直接判断是否有1,或取max则会导致出错。

此 hack 来自方少

J. 读书人

模拟题。

洛谷原题弱化版。

本题代码(有分步解析):

#include <bits/stdc++.h>
using namespace std;
char s[55], a[55], b[55];
char w[20] = " GSBQWSBQY";
int cnt, cnta, cntb;
bool pd_xsd, pd_top0;
bool pd_all0(int n)
{while (n > 0){if (a[n--] != '0')return 0;}return 1;
}
bool pd_W(int n)
{while (n > 5){if (a[--n] != '0')return 0;}return 1;
}
int main()
{cin >> s;int len = strlen(s);for (int i = 0; i < len; i++){if (s[i] == '.'){pd_xsd = 1;break;}}int cnt = len - 1;if (pd_xsd){while (s[cnt--] != '.')b[++cntb] = s[cnt + 1];while (cnt >= 0)a[++cnta] = s[cnt--];}else{for (int i = 0; i < len; i++)a[len - i] = s[i];cnta = len;}if (a[cnta] > '9' || a[cnta] < '0'){if (a[cnta] == '-')cout << 'F';a[cnta--] = 0;}while (cnta > 0 && a[cnta] == '0')a[cnta--] = 0;if (cnta == 0)cout << 0;else{while (cnta){if (a[cnta] != '0'){pd_top0 = 1, cout << a[cnta];if (cnta != 1 && cnta != 5)cout << w[cnta];if (4 < cnta && cnta < 9){if (pd_W(cnta))cout << 'W';}}else if (pd_top0){pd_top0 = 0;if (!pd_all0(cnta)){cout << 0;}}cnta--;}}if (pd_xsd && s[len - 1] != '.')cout << 'D';for (int i = cntb; i > 0; i--)cout << b[i];return 0;
}

这题的难点主要在于整数部分的处理。

先看其他部分:


判断有无小数点:

	 for (int i = 0; i < len; i++){if (s[i] == '.'){pd_xsd = 1;break;}}

将整数和小数部分分开,分别用 a,b 两个数组存下来:

    int cnt = len - 1;if (pd_xsd){while (s[cnt--] != '.')b[++cntb] = s[cnt + 1];while (cnt >= 0)a[++cnta] = s[cnt--];}else{for (int i = 0; i < len; i++)a[len - i] = s[i];cnta = len;}

判断符号位,并去除前导 0。

    if (a[cnta] > '9' || a[cnta] < '0'){if (a[cnta] == '-')cout << 'F';a[cnta--] = 0;}while (cnta > 0 && a[cnta] == '0')a[cnta--] = 0;

整数部分先跳过,小数部分:

    if (pd_xsd && s[len - 1] != '.')cout << 'D';for (int i = cntb; i > 0; i--)cout << b[i];

最后看整数部分:

    if (cnta == 0){cout << 0;// 如果没有整数部分(去除前导 0 导致的),则直接输出 0。}else{while (cnta){ // 处理每一位if (a[cnta] != '0'){pd_top0 = 1, cout << a[cnta];// pd_top0 代表判断是否是 0 而且是连续段中的第一个 0,用于连续 0 的输出。if (cnta != 1 && cnta != 5)cout << w[cnta];// 除了第一位和第五位特殊,其他情况全部可以直接输出单位。if (4 < cnta && cnta < 9){ // 第 5 到 8 位的数字需要考虑是否输出 'W'。if (pd_W(cnta))cout << 'W';}}else if (pd_top0){ // 一段连续的 0,只需要其第一位进行输出,其他的不输出。pd_top0 = 0;if (!pd_all0(cnta)){ // 特殊情况,如果当前位之后全是 0,则不需要输出,否则需要输出。cout << 0;}}cnta--;}}

其中:

第 5 到 8 位的数字需要考虑是否输出 'W'

我们有代码:

bool pd_W(int n)
{while (n > 5){ // 若此时第 5 位到当前位还有非 0 的数字,则不需要输出 'W'if (a[--n] != '0')return 0;}return 1;
}

特殊情况,如果当前位之后全是 0,则不需要输出,否则需要输出。

我们有代码:

bool pd_all0(int n)
{while (n > 0){//判断当前位到最低位是否全是 0if (a[n--] != '0')return 0;}return 1;
}
http://www.hskmm.com/?act=detail&tid=29404

相关文章:

  • pycharm跑python项目易出错的困难
  • 双端队列的0-1BFS
  • Python psycopg2 类库使用学习总结
  • [GenAI] RAG架构演进
  • 24NOIP游记——彼时彼刻
  • 嵌入式-C++面经1
  • 合并区间 - MKT
  • 如何防止员工向第三方 AI 泄露数据?滤海 AI DLP 全方位技术防护方案解析
  • 20232322 2025-2026-1 《网络与系统攻防技术》实验一实验报告
  • 实验1 现代c++编程初体验
  • 冬天快乐
  • P2441M 见过的 tricks
  • 企业大数据战略定位
  • OpenAI加码个性化消费AI技术布局
  • 线性回归 C++ 实现
  • 内存分区
  • Spring Data JPA学习笔记
  • P1112 波浪数 题解
  • 20232411 2025-2026-1 《网络与系统攻防技术》实验一实验报告
  • 使用 Pascal 实现英文数字验证码识别系统
  • PWN手的成长之路-15-jarvisoj_level2_x64
  • 2025.10.12——1绿
  • 价值博弈场的工程实现:构建数字文明的价值免疫系统——声明Ai生成
  • 基于 Rust 的英文数字验证码识别系统设计与实现
  • 2025年两联供室内机厂家最新权威推荐榜:技术实力与市场口碑
  • 2025武汉商铺装修防水厂家最新权威推荐榜:专业施工与品质保
  • 2025铝合金微弧氧化厂家权威推荐榜:表面处理技术实力深度解
  • 2025杉木木方厂家最新权威推荐榜:优质木材与稳定供应口碑之
  • 2025年厂房保养厂家最新权威推荐榜:专业维护与成本控制优选
  • 使用C语言实现重写stm32的启动文件