沪越联赛 - 2024年6月月赛Div2 题解

news/2024/10/5 13:48:36/文章来源:https://www.cnblogs.com/legendcn/p/18287362

问题 A: 替换

题目描述

小明每次注释的时候都写 \(n\)/。小红看了小明的程序,觉得太难看了,那么多 /,所以决定把这些没用/ 都去掉。小红定义了一个宏命令,每次可以将所有连续的 \(m\)/ 替换成空(注意不是空格)
小明得知了小红的企图后非常着急,因为他知道光把 / 都去掉,那么原本注释掉的语句就会被编译,最终变成编译错误。他赶快来阻止小红。时间紧迫,小红只能进行一次操作,她又想用最小的
达到目的。出于对正常程序员的尊重,\(2\)/ 开头的注释(不是小明写的)要不受影响,只有小明写的 \(n\)/ 都会被去掉。

题解

签到题,但是我没过。
我赛时题目理解错了,小红的目的是把所有没用/ 全部去掉,而不是把所有/ 都去掉。

# include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair <int, int> pii;
# define int long longint n; 
signed main ()
{// freopen ("replace.in", "r", stdin);  // freopen ("replace.out", "w", stdout); scanf ("%lld", &n); if (n == 2) return 0; if (n == 4) { printf ("4\n"); return 0; }bool flag = 0; for (int i = 2; i * i <= n; i ++ ){if (n % i == 0){flag = 1; break; }}if (!flag){printf ("%lld\n", n); return 0; }for (int i = 3; i * i <= n; i ++ ){if (n % i == 0 && (n + 2) % i != 0){printf ("%lld\n", i); return 0; }}for (int i = 2; i * i <= n; i ++ ){if (n % i == 0){int t = n / i; if (n % t == 0 && (n + 2) % t != 0){printf ("%lld\n", t); return 0; }}}return 0;
}

问题 B: 马跳三步

题目描述

有一个国际象棋的马在无限大的平面直角坐标系从 \((0,0)\) 开始行走,问 \(3\) 步内,能不能到达指定目标

题解

签到

# include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair <int, int> pii;
//# define int long longstruct node { int x, y, stp; }; 
int dx[8] = {-2, -2, -1, -1, 2, 2, 1, 1}; 
int dy[8] = {-1, 1, -2, 2, -1, 1, -2, 2}; 
bool bfs (int x, int y)
{queue <node> q; q.push ({0, 0, 0}); map <pii, bool> vis; vis[{0, 0}] = 1; while (!q.empty ()){node u = q.front (); q.pop (); if (u.stp > 3) continue; if (u.x == x && u.y == y) return 1; for (int i = 0; i < 8; i ++ ){int nx = u.x + dx[i], ny = u.y + dy[i]; if (vis[{nx, ny}]) continue; vis[{nx, ny}] = 1; q.push ({nx, ny, u.stp + 1}); }}return 0; 
}
signed main ()
{freopen ("knight.in", "r", stdin); freopen ("knight.out", "w", stdout); int T; scanf ("%d", &T); while (T -- ){int ex, ey; scanf ("%d%d", &ex, &ey); if (bfs (ex, ey)) printf ("YES\n"); else printf ("NO\n"); }return 0;
}

问题 C: 加减算式

题目描述

\(n\) 张卡片,卡片上可能是 \(0\) ~ \(9\) 的一位数,也可能是运算符 +-。可以任意排列这 \(n\) 张牌,并计算此时的结果(前导 \(0\) 是被允许的)

请计算,计算结果的最大值和最小值。

题解

赛时口胡除了正解,但是缺少很多细节。

最大值求法:
构造一个最大的数,其他的数都是一位数。
在剩下的一位数中,加大的,减小的。

最小值求法:

  1. 如果没有减号,可以发现,最小值所构成的数位数尽量平均。所以对于每个数维护在最小值中对应的 \(10\) 的幂次。
  2. 跟最大值一样,构造一个最大的数做减法,加小的,减大的
# include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair <int, int> pii;
# define int long long
# define rd(t) read <t> ()
# define mem(a, b) memset (a, b, sizeof (a))
# define fi first
# define se second
# define lc u << 1
# define rc u << 1 | 1
# define debug printf ("debug\n")
const int N = 20, M = (1 << 15) + 5; 
template <typename T> inline T read ()
{T s = 0; int w = 1; char c = getchar (); if (!isdigit (c)) { if (c == '-') w = -1; c = getchar (); }for (; isdigit (c); c = getchar ()) s = (s << 1) + (s << 3) + c - '0';return s * w;
}int n, m; 
char a[N]; 
int b[N], tot, tmp[N], cnt; 
int quan[N]; 
signed main ()
{freopen ("addsub.in", "r", stdin); freopen ("addsub.out", "w", stdout); n = rd (int); for (int i = 1; i <= n; i ++ ) cin >> a[i]; int add = 0, sub = 0; for (int i = 1; i <= n; i ++ ){if (isdigit (a[i]) || a[i] == '0') b[ ++ tot] = a[i] - '0'; else if (a[i] == '+') add ++ ; else sub ++ ; }// cout << sub << " " << add << endl; sort (b + 1, b + 1 + tot, greater <int> ()); string s = "", t = ""; for (int i = 1; i <= tot; i ++ ) s += (char)(b[i] + '0'); // cout << s << endl; for (int i = s.size () - 1; i >= 0; i -- ){t = s[i] + t; if (!sub && add) t = "+" + t, add -- ; if (sub) t = "-" + t, sub -- ; }// cout << t << endl; int sum = 0, op = 1, num = 0; for (int i = 0; i < t.size (); i ++ ){if (isdigit (t[i])) num = num * 10 + (t[i] - '0'); else if (t[i] == '+') sum += op * num, num = 0, op = 1; else sum += op * num, num = 0, op = -1; }sum += op * num; printf ("%lld ", sum); add = 0, sub = 0; for (int i = 1; i <= n; i ++ ){if (a[i] == '+') add ++ ; else if (a[i] == '-') sub ++ ; }if (!sub){sort (b + 1, b + 1 + tot); int he = (n + add - 1) / add; int num = add + 1; for (int i = 1; i <= tot; i ++ ) tmp[i] = b[i]; int cnt = 0; for (int i = 1; i <= tot; i ++ ){if (tmp[i] == 0)cnt ++ ; }if (cnt){int tmptot = tot; tot = 0; for (int i = cnt + 1; i <= tmptot; i ++ ) b[ ++ tot] = tmp[i]; }// for (int i = 1; i <= tot; i ++ ); // 0 0 0 1 2 3 4 5 ++ // 4 6// 1 2 3 0 0 4 5for (int i = tot; i >= tot - num + 1; i -- ) quan[i] = 1; for (int i = 1; i <= num; i ++ ) quan[i] = (tot / num); for (int i = 1; i <= tot % num; i ++ ) quan[i] ++ ; int wei = 2; for (int i = tot - num; i >= num + 1; i -= num){for (int j = i; j >= i - num + 1; j -- ) quan[j] = wei; wei ++ ; }/*7 6 0 0 0 0 0 0 0 0  0  1  1 1 2 3 4 5 6 7 8 9 10 11 12 137 6 6 0 5 0 4 0 3 0 2 1 1 */// cout << endl; // for (int i = 1; i <= tot; i ++ ) cout << quan[i] << " " ;// cout << endl; // return 0; int ans = 0; for (int i = 1; i <= tot; i ++ ) ans += b[i] * pow (10, quan[i] - 1); printf ("%lld\n", ans); return 0; }int tmptot = tot; sort (b + 1, b + 1 + tot); for (int i = 1; i <= tot; i ++ ) tmp[i] = b[i]; tot = 0; for (int i = 1; i <= sub + add; i ++ ) b[ ++ tot] = tmp[i]; for (int i = tmptot; i >= sub + add + 1; i -- ) b[ ++ tot] = tmp[i]; s = "", t = ""; for (int i = 1; i <= tot; i ++ ) s += (char)(b[i] + '0'); for (int i = 0; i < s.size (); i ++ ){t = t + s[i]; if (!add && sub) t = t + "-", sub -- ; if (add) t = t + "+", add -- ; }sum = 0, op = 1, num = 0; for (int i = 0; i < t.size (); i ++ ){if (isdigit (t[i])) num = num * 10 + (t[i] - '0'); else if (t[i] == '+') sum += op * num, num = 0, op = 1; else sum += op * num, num = 0, op = -1; }sum += op * num; printf ("%lld\n", sum); return 0;
}

问题 D: 滚雪球

题目描述

\(H\)\(W\) 列的方格中,有些地方有雪,有些地方没雪。如果一个雪球在 \((X,Y)\) 的雪球可以滚到相邻的四个格子(不能滚到边界)。如果滚到雪上了,雪球大小 \(+1\),否则雪球大小 \(-1\)。如果在某个时刻雪球大小为 \(0\),就不能滚了。

\((X_a,Y_a)\) 有一个大小为 \(A\) 的雪球,人们要把他们滚到 \((X_b,Y_b)\),而且大小需要为 \(B\)。人们想问问你,可不可以。

题解

赛时过了。

发现对于同一个格子,大小不同的时候是不同的状态。所以 visit 数组应该多一维。

# include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair <int, int> pii;
# define int long long
const int N = 55; int n, m; 
int a, xa, ya, b, xb, yb; 
char mp[N][N]; 
struct node { int x, y, stp; }; 
int dx[4] = {1, -1, 0, 0}; 
int dy[4] = {0, 0, 1, -1}; 
bool vis[N][N][4005]; 
bool bfs ()
{queue <node> q; q.push ({xa, ya, a}); memset (vis, 0, sizeof vis); vis[xa][ya][a] = 1; while (!q.empty ()){node u = q.front (); q.pop (); if (!u.stp) continue; if (u.x == xb && u.y == yb && u.stp == b) return 1; for (int i = 0; i < 4; i ++ ){int nx = u.x + dx[i], ny = u.y + dy[i]; int nstp = u.stp + (mp[nx][ny] == '*' ? 1 : -1); if (nx < 1 || nx > n || ny < 1 || ny > m) continue; if (vis[nx][ny][nstp]) continue; vis[nx][ny][nstp] = 1; q.push ({nx, ny, nstp}); }}return 0; 
}
signed main ()
{freopen ("snowball.in", "r", stdin); freopen ("snowball.out", "w", stdout); int T; cin >> T; while (T -- ){cin >> n >> m >> a >> xa >> ya >> b >> xb >> yb; for (int i = 1; i <= n; i ++ ){for (int j = 1; j <= m; j ++ )cin >> mp[i][j]; }if (bfs ()) printf ("Yes\n"); else printf ("No\n"); }return 0;
}

问题 E: 数羊

题目描述

\(wxz\) 睡觉的时候喜欢按照斐波那契数列数羊(第一次 \(1\) 只,第二次 \(2\) 只,第三次 \(3\)\(\cdots\))。但是他有时候会少数一只羊。比如第 \(i\) 次数错了,那么第 \(i\) 次的数量就会变成第 \(i-1\) 次的数量 \(+\)\(i-2\) 次的数量 \(-1\)。(第 \(4\) 次数错了,就会变成:\(1,1,2,2,4,6,10\)

\(wxz\) 数了 \(n\) 次,羊的数量是 \(m\),现在 \(wxz\) 想知道,最少数错了多少次,第 \(n\) 次的羊会变成 \(m\)

题解

这道题有点神仙,但是看完题解感觉十分简单。
经过小数据的模拟,可以发现,减少的羊数也是斐波那契数列。所以,就是要找出最少增加多少个斐波那契数列的项,使得和为错误的数量。

不妨贪心的从 \(fib[n-2]\) 开始做,每次尝试可不可以放入。

# include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair <int, int> pii;
# define int long longint n, m; 
int f[85]; 
signed main ()
{freopen ("count.in", "r", stdin); freopen ("count.out", "w", stdout); scanf ("%lld%lld", &n, &m); f[1] = f[2] = 1; for (int i = 3; i <= n; i ++ ) f[i] = f[i - 1] + f[i - 2]; if (f[n] - m < 0) { printf ("-1\n"); return 0; }int ans = 0; int t = f[n] - m; for (int i = n - 2; i >= 1; i -- ){if (f[i] <= t){t -= f[i]; ans ++ ; }if (!t) break; }printf ("%lld\n", ans); return 0;
}

## 问题 F: 波折数列

题目描述

定义一个由 \(a,b,c\) 组成的序列是波折的,当且仅当:

  1. \(a,b,c\) 互不相等
  2. \(b\) 是最小的或者是最大的

\(n\) 个整数构成的序列是波折的,当且仅任意三个连续子序列都是波折的。
\(1\) ~ \(n\) 的所有排列中,有多少个是波折的。

题解

赛时过了

一开始,我以为是打表。但是我太菜了,打表程序跑到 \(20\) 就没法跑了。

不能打表,那可以考虑 \(dp\)(不然这场比赛没有 \(dp\) 了)

考虑 \(dp_{i,0}\) 表示有 \(i\) 个人且 \(i\) 个人结尾的方法数,\(dp_{i,1}\) 表示有 \(i\) 个人且第 \(i\) 个人为开头方法数。

\(i\) 个人排列的方法数就是

\[ans_i+=dp_{j,0}*dp_{i-j-1,i}\times \binom{i-1}{j} \]

因为不确定前面 \(j\) 个人的顺序,所以要在 \(i-1\) 个人中选 \(j\) 个人出来。

容易发现,\(i\) 是结尾的个数和 \(i\) 是开头的个数相等。所以:

\[dp_{i,0}=dp_{i,1}=\frac{ans_i}{2} \]

# include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair <int, int> pii;
# define int long long
# define debug printf ("debug\n")
const int N = 3005, p = 1e9 + 7; int n; 
int getinv (int a, int b = p - 2)
{int ans = 1; while (b){if (b & 1) ans = ans * a % p; a = a * a % p; b >>= 1; }return ans; 
}
int c[N][N]; 
void init ()
{for (int i = 0; i < N; i ++ ){for (int j = 0; j <= i; j ++ ){if (!j) c[i][j] = 1;else c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % p;}}
}
int dp[N][2];
int sum[N];
signed main()
{freopen ("zigzag.in", "r", stdin); freopen ("zigzag.out", "w", stdout); scanf ("%lld", &n); init (); sum[1] = 1;sum[2] = 2;dp[0][0] = dp[0][1] = 1;dp[1][0] = dp[1][1] = 1;dp[2][0] = dp[2][1] = 1;for (int i = 3; i <= n; i ++ ){for (int j = 0; j < i; j ++ )sum[i] = (sum[i] + dp[j][0] * dp[i - j - 1][1] % p * c[i - 1][j] % p) % p;dp[i][0] = dp[i][1] = sum[i] * getinv (2) % p;}printf ("%lld\n", sum[n]); return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/739460.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C#学习笔记-事件

事件事件是类的一种成员,能够使类或对象具备通知能力。事件用于对象或类间的动作协调和信息传递。假设类A有某个事件,当这个事件发生时,类A会通知并传递事件参数(可选)给有订阅这个事件的类B,类B根据拿到的事件信息对事件进行响应处理。 事件模型 事件模型的5个组成部分:…

将nodejs迁移到D盘

参考双击安装,指定d盘查看文件夹查看环境变量,自动添加如下Path=D:\software\nodejs\打开cmd验证C:\Users\dogle>node -v v18.14.2C:\Users\dogle>npm -v 9.5.0C:\Users\dogle>echo %PATH% C:\Program Files (x86)\Common Files\Oracle\Java\javapath;C:\WINDOWS\sy…

bluez 入门

**核心模块**:位于系统的最底层,直接与蓝牙硬件进行交互。核心模块实现了蓝牙的基础协议如HCI (Host Controller Interface),并通过DBUS提供API给上层应用。 **服务守护进程(bluetoothd)**:作为系统的守护进程运行,它处理所有的蓝牙服务和配置,如设备配对、连接管理、配…

chrome 浏览器如何设置不保存表单信息

chrome 浏览器如何设置不保存表单信息如何关闭表单自动填充(测试环境Chrome浏览器) https://download.csdn.net/blog/column/7594878/100576004如何禁用谷歌浏览器中的表单自动填充功能? https://zh-cn.fairsyndication.com/222-how-to-disable-form-autofill-in-google-chr…

数字设计--CDC

异步信号与同步信号 同步信号 频率相同,相位相同的两个信号 频率相同,相位差一定的两个信号 不同频率的两个信号也可能是同步的,比如分频出来的两个信号 异步信号 频率不同的两个信号 频率相同但相位差不定的两个信号 跨时钟域就是要解决信号从异步信号之间传输的问题。 亚稳…

数字设计--亚稳态

亚稳态 FPGA 等数字设备中的所有寄存器都定义了信号时序要求----允许每个寄存器在其输入端正确捕获数据并产生输出信号。为确保可靠操作,寄存器的输入必须在时钟边沿之前的最短时间(建立时间 setup time 或 \(t_{su}\))和时钟边沿之后的最短时间(保持时间 hold time 或 \(t…

数字设计--门控时钟与时钟切换

门控时钟(ICG) 使用门控时钟的原因 芯片功耗组成中,大部分是由时钟树消耗掉的。因为这些时钟树在系统中具有最高的切换频率,而且有很多时钟buffer,并且为了最小化时钟延时,它们通常具有很高的驱动强度。此外,即使输入和输出保持不变,接收时钟的触发器也会消耗一定的功耗。…

ComfyUI进阶篇:ComfyUI核心节点(二)

ComfyUI核心节点(二) 前言: 学习ComfyUI是一场持久战。当你掌握了ComfyUI的安装和运行之后,会发现大量五花八门的节点。面对各种各样的工作流和复杂的节点种类,可能会让人感到不知所措。在这篇文章中,我们将用通俗易懂的语言对ComfyUI的核心节点进行系统梳理,并详细解释每…

题目集7~8

由于个人原因,最后两次题目集未提交,对自己的放纵感到愧疚,后期的补练我也会抽出时间完成这两道题 经过分析,题目集7,是在前面的基础上加上了一个新概念:互斥开关,以及模拟一种受控窗帘, 在我的想法,互斥开关便可当作两个普通开关去完成电路,窗帘则是新增一个用电器。…

EtherCAT转Profinet网关配置说明第一讲:配置软件安装及介绍

网关XD-ECPNS20为EtherCAT转Profinet协议网关,使EtherCAT协议和Profinet协议两种工业实时以太网网络之间双向传输 IO 数据。适用于具有EtherCAT协议网络与Profinet协议网络跨越网络界限进行数据交换的解决方案。 网关XD-ECPNS20为EtherCAT转Profinet协议网关,使EtherCAT协议…

4、flask-项目拆分

项目的拆分其实就是将app.py中的工作拆分开来、类似Django一样、每个项目都把路由模板和试图函数分开写 app.py # 路由 + 视图函数from flask import Blueprint from models import *#蓝图 # 创建蓝图对象 # 第一个参数:蓝图的名字 # 第二个参数:蓝图的包名 blue = Blueprin…

2-SAT 问题

2-SAT 问题 模型有 \(n\) 个布尔类型的变量 \(x_1, x_2, \ldots, x_n\),有 \(m\) 条限制形如 \(x_i \space [\operatorname{or}/\operatorname{and}]\space x_j=[1/0]\). 求一组符合要求的解。核心问题只需要考虑有没有解。 对于每个变量都只有两种取值:\(0/1\),那么把每…