AtCoder Beginner Contest 425 ABCDEF 题目解析

news/2025/9/27 22:32:53/文章来源:https://www.cnblogs.com/stelayuri/p/19115823

A - Sigma Cubes

题意

给定一个正整数 \(N\),求出 \(\displaystyle \sum_{i=1}^N (-1)^i \times i^3\)

代码

void solve()
{int n, sum = 0;cin >> n;for(int i = 1; i <= n; i++){if(i % 2 == 1)sum -= i * i * i;elsesum += i * i * i;}cout << sum;
}

B - Find Permutation 2

题意

给定一个长度为 \(N\) 的整数序列 \(A=(A_1,A_2,\ldots,A_N)\) ,保证 \(A\) 内的整数要么是 \(-1\) ,要么是介于 \(1\)\(N\) 之间的整数。

请尝试将所有 \(-1\) 替换为任意 \(1\)\(N\) 之间的整数,使得最终整数序列是一个 \(N\) 的全排列。或是判断答案不存在。

思路

首先对于输入的数组,不存在答案的情况只可能是因为出现了多个重复的正整数。

所以可以先借助计数数组,或是循环嵌套,判断是否出现了除 \(-1\) 以外的重复数字。

如果答案存在,就对于每个 \(-1\),找一个没出现过的数字去将这个 \(-1\) 替代掉即可。这一步也可以借助计数数组+循环嵌套完成,或是双指针算法等。

代码

int n, a[15];
bool vis[15]; // 判断每种数字是否出现void solve()
{cin >> n;for(int i = 1; i <= n; i++){cin >> a[i];if(a[i] == -1) // -1 暂时不处理continue;if(vis[a[i]] == true) // 如果 a[i] 已经出现过{cout << "No";return;}vis[a[i]] = true;}cout << "Yes\n";for(int i = 1; i <= n; i++){if(a[i] == -1) // 找一个没用过的数字替代掉 -1{for(int j = 1; j <= n; j++)if(vis[j] == false) // j 没有用过{vis[j] = true;a[i] = j; // 放在 i 位置break;}}cout << a[i] << " ";}
}

C - Rotate and Sum Query

题意

给你一个长度为 \(N\) 的整数序列 \(A=(A_1,A_2,\ldots,A_N)\)

请按顺序处理 \(Q\) 个查询。查询有两种类型,格式如下:

  • 1 c:重复执行 \(c\) 次操作,每次将 \(A\) 的第一个元素移动到末尾。
  • 2 l r:输出 \(\displaystyle \sum_{i=l}^r A_i\) 的值。

思路

考虑第一种操作,数组元素移动到末尾后,如果还想保持原本的下标关系,那我们就得把其它所有数字全部往前移动一位,这样的操作时间复杂度是 \(O(N)\) 的,当操作次数较多时会超时。

但发现移动 \(N\) 次之后数组会还原回一开始的样子,所以这里我们不考虑移动数组,而是采用循环队列的做法,用一个队首变量 \(f\) 来标记当前数组第一个元素的实际下标即可。每次执行操作一,相当于当前队首跑到了队尾,而原本队首的后一个数成为了队首,所以只需要让队首变量 \(f := f+1\) 即可。当 \(f\) 指向最后一个位置时,则回到第一个位置。

如果我们想要获得当前数组内第 \(i\) 个位置的元素,其实际下标便可以通过队首往后数 \(i+1\) 个位置得到,即 \(f + i - 1\)。但如果 \(f + i - 1 \gt n\),则需要回到第一个位置,对应下标为 \(f + i - 1 - n\)

发现对于是否超出第 \(n\) 个位置的讨论较为繁琐,所以这里可以稍微借助“化环为链”的技巧,将原本的 \(A\) 数组复制一份拼在 \(A\) 后面,变成一个长度为 \(2n\) 的数组 \(A_1, A_2, \dots, A_n, A_1, A_2, \dots, A_n\)。这样就可以不用去考虑分类讨论,直接就能用计算得到的 \(f + i - 1\) 下标。

然后考虑第二种操作,假如现在队首下标为 \(f\),要求你求出 \([l, r]\) 区间内的总和,那么对应的实际下标就是 \([f + l - 1, f + r - 1]\),静态区间求和,借助前缀和思想预处理后求解。

时间复杂度 \(O(N+Q)\)

代码

typedef long long ll;int n, q;
int a[400005]; // 两倍空间
ll s[400005]; // a[] 的前缀和void solve()
{cin >> n >> q;for(int i = 1; i <= n; i++){cin >> a[i];a[i + n] = a[i]; // 复制一份放在 a 后面}for(int i = 1; i <= 2 * n; i++)s[i] = s[i - 1] + a[i]; // 求前缀和int f = 1; // 当前第一个元素对应下标while(q--){int op;cin >> op;if(op == 1){int c;cin >> c;f += c;if(f > n) // 超过最后一个位置则回到第一个f = f - n;}else{int l, r;cin >> l >> r;// 求 [f + l - 1, f + r - 1] 的总和cout << s[f + r - 1] - s[f + l - 2] << "\n";}}
}

D - Ulam-Warburton Automaton

题意

有一个大小为 \(H \times W\) 的网格图。记第 \(i\) 行第 \(j\) 列的网格坐标为 \((i, j)\)

\(S_{i, j}\)#,则说明坐标 \((i, j)\) 的网格一开始是黑色的;如果 \(S_{i, j}\). 则说明其一开始是白色的。

请执行以下操作 \(10^{100}\) 次:

  • 将此时网格图中所有的四周仅有一个单元格为黑色白色单元格在同一时间全部涂成黑色。这里的“四周”表示上下左右四个方向的相邻格子。

求操作结束后,黑色单元格的总数。

思路

我们只会把白色单元格改成黑色的,所以涂色次数最多不会超过单元格总数。并且每次涂色会影响到的格子只有周围四个格子,所以可以采用宽搜解题。

但这题如果使用单个队列的普通宽搜做法,对于题目中的“在同一时间全部涂成黑色”这个条件可能就无法满足。也就是说,有可能网格图中某个白色单元格原本周围没有相邻的黑色网格,但在某一时刻周围一次性出现了两个及以上的黑色网格,这种情况根据题意是不会把这个白色单元格涂黑的。但我们如果采取普通宽搜的话,肯定是一个格子一个格子慢慢涂色的,有可能会导致误判。

所以本题的宽搜需要采取滚动队列等类似做法,拿两个队列 \(A, B\) 交替进行搜索,以保证“同时发生”这个条件得以满足。例如,一开始将所有要搜索的坐标先存到队列 \(A\) 中,然后开始搜索队列 \(A\) 内的每个网格。每次发现某个网格周围有一个白色单元格可以被涂黑时,在入队的时候先放到队列 \(B\) 中去,等到队列 \(A\) 内所有要搜索的网格全部搜完之后,再开始搜索队列 \(B\),以此交替执行。

特别需要注意,当发现有白色单元格可以被涂黑,在将其加入另一个队列的时候,我们可以标记这个位置已经被访问过了,但此时绝对不能直接改变这个位置的颜色,防止影响到当前队列其它网格的判断。直到当前队列搜索完之后,再把刚才需要发生颜色更改的所有网格统一改掉。这一步可以再借助 vector 等容器辅助存储。

时间复杂度 \(O(H \times W)\)

代码

const int dx[4] = {-1, 1, 0, 0};
const int dy[4] = {0, 0, -1, 1};struct point
{int x, y;
};queue<point> q[2];void solve()
{int n, m;cin >> n >> m;vector<vector<char>> mp(n + 1, vector<char>(m + 1));vector<vector<char>> vis(n + 1, vector<char>(m + 1, false)); // 标记数组for(int i = 1; i <= n; i++)for(int j = 1; j <= m; j++)cin >> mp[i][j];for(int i = 1; i <= n; i++)for(int j = 1; j <= m; j++)if(mp[i][j] == '#') // 从一开始的所有黑色格子出发搜索{q[0].push({i, j});vis[i][j] = true;}int cur = 0; // 当前正在搜索的是哪个队列 0/1while(!q[0].empty() || !q[1].empty()) // 只要至少有一个队列没搜完,就还能继续搜{int nxt = cur ^ 1; // 另一个队列的编号vector<point> G; // 当前这次搜索会让哪些格子变成黑色,先存起来,搜完后统一改颜色while(!q[cur].empty()) // 只要当前这个队列不为空{point u = q[cur].front();q[cur].pop();for(int i = 0; i < 4; i++) // 找周围可以影响到的下一个点{point v = {u.x + dx[i], u.y + dy[i]};if(v.x < 1 || v.y < 1 || v.x > n || v.y > m) // 越界continue;if(mp[v.x][v.y] == '#') // 已经涂过色了continue;if(vis[v.x][v.y] == true) // 已经搜索过了continue;int cnt = 0; // 记录其周围有多少格子是黑色的for(int j = 0; j < 4; j++){point t = {v.x + dx[j], v.y + dy[j]};if(t.x >= 1 && t.x <= n && t.y >= 1 && t.y <= m && mp[t.x][t.y] == '#')cnt++;}if(cnt == 1) // 恰好周围只有一个黑色格子{// 先标记并入队,但不要在这里直接改颜色,防止影响到当前这一次搜索过程中其他点的判断q[nxt].push(v);vis[v.x][v.y] = true;G.push_back(v);}}}for(point &p : G) // 搜完后,把这一次搜索入队的每个点统一改成黑色mp[p.x][p.y] = '#';cur = nxt; // 交换队列}int ans = 0;for(int i = 1; i <= n; i++)for(int j = 1; j <= m; j++)ans += (mp[i][j] == '#');cout << ans;
}

E - Count Sequences 2

题意

给定一个正整数 \(N\) 和一个长度为 \(N\) 的正整数序列 \(C=(C_1,C_2,\ldots,C_N)\)

求满足以下所有条件的不同正整数序列的个数,输出其除以 \(M\) 的余数:

  • 序列的所有元素都在 \(1\)\(N\) 之间。
  • 对于每个 \(i=1,2,\ldots,N\),数 \(i\) 在序列中恰好出现 \(C_i\) 次。

有多组数据。模数 \(M\) 对于单个测试文件的所有测试数据是通用的。

思路

为避免公式混淆,下面将数字 \(i\) 出现的次数记作 \(T_i\) 次。

\(S = \sum\limits_{i=1}^N T_i\)

这是一个经典的多重集排列问题。先考虑全排列数量,即 \(A_S^S = S!\)

然后对于整数 \(i\),其在序列中恰好出现了 \(T_i\) 次,由于相同数字之间是不可区分的,所以需要除去该种数字内部的全排列数量,即 \(A_{T_i}^{T_i}\)。对于每种数字,均将其内部的重复方案数从总全排列方案中除去,故最终答案为:

\[\large \frac{A_S^S}{A_{T_1}^{T_1} \times A_{T_2}^{T_2} \times \dots \times A_{T_N}^{T_N}} = \frac{S!}{T_1! T_2! \dots T_N!} \]

如果模数 \(M\) 为一个大质数,我们可以很方便地通过递推预处理出每一项的阶乘,再通过费马小定理结合快速幂求出每项阶乘的逆元,直接计算即可得到答案。但本题的模数 \(M\) 并不是一个质数,因此该方法无效。

如果要求解的原值与模数 \(M\) 互质,我们还可以借助扩展欧几里得算法求解逆元。但本题 \(M\) 并没有保证与所有阶乘互质,因此该方法也无效。

所以最终只能从公式角度出发。这个公式是经典的“多项式系数”,描述多项式 \((x_1 + x_2 + \dots + x_m)^n\) 的展开式中,项 \(x_1^{n_1}x_2^{n_2}\dots x_m^{n_m}\) 的系数,即 \(\dfrac{(n_1+n_2+\dots+n_m)!}{n_1!n_2!\dots n_m!}\)

我们可以从该系数的定义入手。这个系数可以描述为将 \(S\) 个物品分为 \(N\) 组,每组分别有 \(T_1, T_2, \dots, T_N\) 个物品,问不同的分法数量。先从 \(S\) 个物品中选出 \(T_1\) 个物品分到第 \(1\) 组,再在剩下的 \(S-T_1\) 个物品中选出 \(T_2\) 个物品分到第 \(2\) 组,以此类推,方法数可以描述为:

\[\large C_S^{T_1} \times C_{S-T_1}^{T_2} \times C_{S-T_1-T_2}^{T_3} \dots C_{T_N}^{T_N} \]

结合杨辉三角预处理组合数后求解即可。

时间复杂度 \(O(S^2 + N)\),其中 \(S_{\max} = 5000\)

代码

typedef long long ll;ll mod;
ll C[5005][5005];// 预处理组合数
void init()
{for(int i = 0; i <= 5000; i++){C[i][0] = C[i][i] = 1;for(int j = 1; j < i; j++)C[i][j] = (C[i-1][j-1] + C[i-1][j]) % mod;}
}int a[300005];void solve()
{int T;cin >> T >> mod;init();while(T--){int n;cin >> n;int sum = 0;for(int i = 1; i <= n; i++){cin >> a[i];sum += a[i];}ll ans = 1;for(int i = 1; i <= n; i++){ans = ans * C[sum][a[i]] % mod;sum -= a[i];}cout << ans << "\n";}
}

F - Inserting Process

题意

给定一个长度为 \(N\) 且由小写字母组成的字符串 \(T\)

求满足以下所有条件的字符串序列 \(s=(s_0,s_1,\ldots,s_N)\) 的个数,输出其除以 \(998\,244\,353\) 的余数:

  • \(s_0\) 是空字符串。
  • 对于 \(i=1,2,\ldots,N\) 来说,字符串 \(s_{i}\) 是通过在 \(s_{i-1}\) 的任意位置(可能是开头或结尾)插入一个任意字符得到的。
  • \(s_N=T\)

思路

考虑与题意相反的操作,从 \(s_N = T\) 出发,每次任意删除一个字符,最后删到 \(s_0 = \text{空}\)

由于 \(N \le 22\),范围较小,考虑借助一个长度为 \(N\)二进制状态来描述每个字符目前是否已经被删除。\(0\) 表示已被删除,\(1\) 表示未被删除。接下来考虑状压 DP。

dp[sta] 表示将字符串删到 sta 这个二进制值所表示的状态时,所能得到的不同序列数量。

明显可以得到初始状态为 dp[(1 << n) - 1] = 1,表示一开始一个字符都还没删除的情况。

接下来考虑倒序枚举状态,对于状态 sta,如果其二进制上 \(2^j\) 这一位仍为 \(1\),则可以考虑删去该位所对应的字符,获得新状态 sta ^ (1 << j),并将上一状态的答案数量加入到新状态的答案中,即 dp[sta ^ (1 << j)] += dp[sta]

但在删除的过程中,我们需要注意一种特殊情况。例如对于字符串 \(\tt abbc\),删除第二个字符 \(\tt b\) 与删除第三个字符 \(\tt b\) 所能得到的新字符串均为 \(\tt abc\),两种删除情况各自对应的二进制状态分别为 \(\tt 1011\)\(\tt 1101\),但很明显我们不能把这两种情况当作是两种不同的状态。所以在过程中我们需要加一个限制条件:如果当前删除的这种字符在字符串中的出现情况是连续的一段,那么我们每次就只删除这段连续区间最左侧(或者只删除最右侧)的字符,以此保证不会重复计算方案。

时间复杂度 \(O(N \times 2^N)\)

代码

const int mod = 998244353;int dp[1 << 22];void solve()
{int n;string t;cin >> n >> t;dp[(1 << n) - 1] = 1; // 一个字符都还没删除的情况for(int sta = (1 << n) - 1; sta >= 0; sta--){char pre = 0; // 保证不是小写英文字母 ASCII 即可,表示上一个未被删除的字符for(int i = 0; i < n; i++)if(sta >> i & 1) // 如果 i 这个字符还存在{if(t[i] != pre) // 与上一个字符不同,说明是新的一段连续字符的第一个位置,可以删除{int nxt = sta ^ (1 << i); // 计算删除 2^i 位后的下个状态dp[nxt] = (dp[nxt] + dp[sta]) % mod;}pre = t[i];}}cout << dp[0];
}

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

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

相关文章

网页设计后怎么上传到网站曰本免费一级a做爰视频网站

文字描边想要在网页里实现文本描边效果&#xff0c;在以前只能使用Photoshop等来实现&#xff0c;但现在只需要一个text-stroke属性&#xff0c;即可轻松做到文本描边&#xff0c;渐变文本描边&#xff0c;甚至图片文本描边。01语法text-stroke: text-stroke是一个复合属性&…

p2p免费网站建设广告推广有哪些平台

pipeline自动化&#xff0c;提交代码后&#xff0c;就自动打包&#xff0c;打包成功后自动发布 第一步 pipeline提交代码后&#xff0c;自动打包。 1 在Repos,分支里选择要触发的分支&#xff0c;这里选择cn_china,对该分支设置分支策略 2 在生产验证中增加新的策略 3 在分支安…

阿里云官网首页德阳seo网站建设

目录 对 Redux 的理解&#xff0c;主要解决什么问题&#xff1f;Redux 原理及工作流程 对 Redux 的理解&#xff0c;主要解决什么问题&#xff1f; Redux是一个用于管理数据状态和UI状态的JavaScript应用工具&#xff0c;主要解决了在复杂JavaScript单页应用&#xff08;SPA&a…

maven打包依赖

4.0.0 <groupId>com.zhihe</groupId> <artifactId>testPlC</artifactId> <version>1.0</version> <packaging>jar</packaging><name>testPlC</name> <…

sg.如何使用PySimpleGUI调试器窗口

PySimpleGUI调试器窗口是开发者在代码运行时实时监控变量、执行交互式命令的强大工具,其使用方法及核心功能如下: 一、核心使用步骤启用异步窗口模式 调试器依赖异步窗口(非阻塞读取)工作,需在read()方法中设置ti…

对话汇总:从东方哲学到可计算架构的演进

对话汇总:从东方哲学到可计算架构的演进 声明:Ai辅助创作/岐金兰,技术门外汉 一、 起源:对AI伦理困境的哲学批判与东方方案的提出 对话始于一份名为《空白金兰契:一种应对AI伦理价值困境的东方方案及其批判性审视…

遵义网站建设网帮你网站备案证书查询

转载公众号 | DataFunTalk 合作分享&#xff1a;Jesus Barrasa-Neo4j-欧洲区售前和技术总监合作分享&#xff1a;丁可-Neo4j-亚太区高级技术顾问编辑整理&#xff1a;吴祺尧-加州大学圣地亚哥分校出品平台&#xff1a;DataFunTalk导读&#xff1a;Neo4j近年来与众多公司合作&am…

25.9.27 继续MyBatis

逐渐入门第一个框架,学习应用层面的东西比之前纯理论的知识有趣不少,实际内容比想象中多,争取先吃透掌握熟练吧。

MoeCTF 2025 二进制漏洞审计:boomboom_revenge

前情提要 栈溢出漏洞,简单的校验逻辑,但很容易被唬住,需要一点耐心。 题目分析 你可以轻易爆破我们的系统,但是一个不可泄露的“canary”你又该如何应对? 你可能需要使用 Python ctypes 包来直接调用 C 库函数。 …

跟brocode用c语言做tictoktoe井字棋 - 指南

跟brocode用c语言做tictoktoe井字棋 - 指南pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "…

集训总结(九)

9.24~9.26总结9.24 P11770 檐牙覆雪 暴力很好写,直接枚举即可。单次询问复杂度 \(O(nlogn)\)。打个表,发现每个地方的最大雪堆都是由它的最大质因子位置转移而来. 设 \(f_i\) 表示最后 \(i\) 处最大雪团体积,则有转…

Spring Cloud构建分布式微服务架构的完整指南 - 指南

Spring Cloud构建分布式微服务架构的完整指南 - 指南2025-09-27 22:21 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; dis…

.net网站开发全过程网站域名做301

目录 初始化列表 static成员 C11对于非静态成员变量初始化 友元 友元函数 友元类 总结 初始化列表 我们知道&#xff0c;在学习构造函数时&#xff0c;我们知道对象的成员变量的初始化我们是在构造函数函数体内进行初始化的&#xff0c;还有没有其它初始化成员变量的方…

完整教程:操作系统之初识Linux

完整教程:操作系统之初识Linuxpre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco&quo…

XJSOJ优化(Stylus脚本)

/* XJSOJ Ultimate Smart Theme - 全面优化与重构 / / 版本: 3.0 - 完整结合版 / / 功能:包含基础圆润优化 + Smart Luogu式深度重构 */ /* === 基础重置与全局样式 === */{ border-radius: 8px !important; transiti…

使用mpm-itk让Apache以不同用户身份运行的完整指南

本文详细介绍了如何使用Apache的mpm-itk模块实现每个虚拟主机以不同用户身份运行,解决WordPress开发和生产环境中的文件权限问题,包含Docker容器配置和PHP邮件功能故障排除方案。使用mpm-itk让Apache以不同用户身份运…

sg.如何打开PySimpleGUI调试器窗口?

在PySimpleGUI中,调试器窗口的打开方式主要有以下三种,每种方式均适用于不同调试场景,且均通过内置调试器实现: 方法一:使用show_debugger_window()函数适用场景:需要快速查看变量值或交互式执行代码时。 操作步…

第6篇、Flask 表单处理与用户认证完全指南:从零到实战

标签:Python Flask Web开发 表单验证 Session Cookie 用户认证 安全编程🎯 为什么选择这篇文章? 在Web开发的世界里,表单处理和用户认证是每个开发者必须掌握的核心技能。无论是构建电商网站、社交平台还是企业管…

做视频网站收费标准wordpress.org密码

近日&#xff0c;全球IT市场研究和咨询公司Gartner发布最新报告《Magic Quadrant™ for Cloud Database Management Systems》&#xff08;全球云数据库管理系统魔力象限&#xff09;。全自研分布式数据库 OceanBase 入选“荣誉提及”&#xff0c;2022 年推出的云数据库 OB Clo…

腾讯开源 AudioStory!能生成 150 秒故事长音频,还会剧情拆解 + 自动配乐 - 详解

腾讯开源 AudioStory!能生成 150 秒故事长音频,还会剧情拆解 + 自动配乐 - 详解2025-09-27 22:09 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overf…