系列文章目录
文章目录 ____.....%&#@同学们#%&____
前言
这是系列周赛的第二次,于5月13日8:30开始,12:00结束。
本次比赛一共有6道题,题目信息如下:
题目序号 | 题目名称 | 时间限制 | 空间限制 | 题目类型 | 评测方式 | 考查知识 | 题目难度 |
---|---|---|---|---|---|---|---|
1 | 行走的机器人 robot | 1000ms | 256MiB | 传统题 | 文本比较 | 模拟/深搜 | 中等 |
2 | 多米诺骨牌涂色 paint | 2000ms | 256MiB | 传统题 | 文本比较 | 递推 | 中等+ |
3 | 最小得分 mex | 1000ms | 512MiB | 传统题 | 文本比较 | 中等+ | |
4 | 幸运数字 lucky | 2000ms | 512MiB | 传统题 | 文本比较 | 数论(gcd) | 难 |
5 | 无向图与函数 grafun | 1000ms | 512MiB | 传统题 | 文本比较 | 图论与前缀和 | 难 |
6 | 最小子集 subset | 1000ms | 256MiB | 传统题 | 文本比较 | 二分图 | 难 |
T1 行走的机器人 robot
题目描述
Bob 对机器人进行了编程,让它在平面迷宫中行走。 迷宫有一些障碍。 空单元格由字符".“表示,障碍物由”#"表示。 迷宫中只有一个机器人。
它的起始位置用字符"S"表示。 这个位置没有任何障碍。 迷宫中也只有一个出口,用字符"E"表示。 这个位置没有任何障碍。
机器人只能向上、向左、向右或向下移动。 Bob 给机器人编程时,写下了一串整数,由其中若干个0,1,2,3组成。
他打算让每个数字对应一个不同的方向,机器人会按照指示到达出口。 不幸的是,他忘记了每个数字分配的是什么方向。
机器人会自动将0,1,2,3随机映射到不同方向,然后按照给定的指令顺序进行操作。如果指令导致机器人离开迷宫边缘或撞到障碍物,机器人就会崩溃。如果机器人在任意时刻到达出口,那么机器人将停止且不执行后续指令。
Bob 想确定有多少种不同的方向映射方案能够将机器人到达出口。
输入格式
第一行输入两个整数n 和m,表示迷宫行数和列数。
接下来的n行每行恰好包含m个字符,表示迷宫。
迷宫中的每个字符都是".“, “#”,“S"或"E”。
迷宫中将恰好有一个"S"和一个"E”。
最后一行将包含一个字符串s,表示给机器人的指令。
输出格式
输出一个整数,表示能够让机器人到达出口的方向映射方案数。
样例
样例输入1
5 6
. . . . .#
S . . . .#
.# . . . .
. # . . . .
. . . E . .
333300012
样例输出1
1
样例输入2
6 6
. . . . . .
. . . . . .
. .SE. .
. . . . . .
. . . . . .
. . . . . .
01232123212302123021
样例输出2
14
样例输入3
5 3
. . .
.S.
###
.E.
. . .
3
样例输出3
0
样例解释
样例说明1
只有一种映射方案:
0 ——> D, 1——> L, 2——> U, 3——> R;其中D表示向下,L表示向左,U表示向上,R表示向右。
数据范围与提示
·2<=n,m<=50;
·1<=|s|<=100,其中|s|表示字符串s的长度
·对于任意的i,si为整数,且0<=si<=3;
·迷宫中的每个字符都是".“, “#”, “S"或"E”,且迷宫中有且仅有一个"S"和一个"E”。
题目分析
法一:模拟
思路:
一看样例,我们就知道这道题完全可以全排列出字符串所代表的意义的每一种情况。然后直接利用二维数组就行模拟。
代码结构:
1.主函数内完成输入二维数组,边输入边记录起点的位置。
2.进行全排列(可以在主函数内也可以再写一个函数)。
3.在fin函数内,根据排列的情况逐一将字符串与其对应:
if (s[i] - 48 == a) f++;
if (s[i] - 48 == b) ba++;
if (s[i] - 48 == c) f--;
if (s[i] - 48 == d) ba--;
注:此处的f代表横坐标,ba代表纵坐标(下文也一样)。
4.判断边界及是否到达终点,并返回至主函数。
5.主函数接收到返回值,改变sum的值。
注意:
1.输入时注意顺序,先输入数组再输入字符串(犯错人:zyc);
2.全排列注意边界及判断条件:(犯错人:lx)
for (int d = 0; d <= 3; d++) {
for (int l = 0; l <= 3; l++) {
if (l == d) continue;
for (int u = 0; u <= 3; u++) {
if (u == d || u == l) continue;
for (int r = 0; r <= 3; r++) {
if (r == d || r == l || r == u) continue;
if (fin(d, l, u, r, fro, bac)) sum++;
}
}
}
}
3.注意判断边界:
if (f > n || f < 1 || ba > m || ba < 1) return 0;
4.注意循环内的循环变量不能和其他变量同名(犯错人:zyc).
代码:
#include <bits/stdc++.h>
using namespace std;
int n, m, fro, bac, sum;
string s;
char p[55][55];
bool fin(int a, int b, int c, int d, int f, int ba){
for (int i = 0; i <= int(s.size()) - 1; i++) {
if (s[i] - 48 == a) f++;
if (s[i] - 48 == b) ba++;
if (s[i] - 48 == c) f--;
if (s[i] - 48 == d) ba--;
if (p[f][ba] == '#') return 0;
if (p[f][ba] == 'E') return 1;
if (f > n || f < 1 || ba > m || ba < 1) return 0;
}
return 0;
}
int main() {
// freopen("robot.in", "r", stdin);
// freopen("robot.out", "w", stdout);
cin >> n >> m;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
cin >> p[i][j];
if (p[i][j] == 'S') fro = i, bac = j;
}
}
cin >> s;
for (int d = 0; d <= 3; d++) {
for (int l = 0; l <= 3; l++) {
if (l == d) continue;
for (int u = 0; u <= 3; u++) {
if (u == d || u == l) continue;
for (int r = 0; r <= 3; r++) {
if (r == d || r == l || r == u) continue;
if (fin(d, l, u, r, fro, bac)) sum++;
}
}
}
}
cout << sum;
return 0;
}
法二:深搜
T2 多米诺骨牌涂色 paint
T3 幸运数字 lucky
分析
看题可知,本题暴力枚举一定超时(不然怎么可能是第四题 )。这时,我们应该想到欧拉定理。
思路:
1.暴力枚举 期望得分:50pts。
2.令m=9*L/gcd(8,L),若gcd(10,m)!=1。无解。
3.枚举1~phi(m)因子,若d|phi(m)且10^d同余1模m,答案x=d(min),期望得分:70pts.
4.龟速乘。期望得分:100分。(主要防止超long long)。
代码:
1.gcd
ll gcd1(ll a, ll b) { //辗转相除法
ll r;
while (b > 0) r = a % b, a = b, b = r;
return a;
}
2.lucky
ll lucky() { //根据欧拉定理求最小值
ll u = fai(m), ans = 0;
for (ll i = 2; i * i <= u; i++ ) {
//cout <<i ;
if (u % i == 0) {
if (_pow(10, i, m) == 1) return i;//单调递增,直接返回
if (_pow(10, u / i, m) == 1) ans = u / i;//本来就是单调递减,所以不需要min函数
}
}
return ans;
}
3.求phi
ll fai(ll m) {
ll ans = m;
for (ll i = 2; i * i <= m; i++)
if (m % i == 0) {
ans = ans / i * (i - 1);//1-1/pi
while (m % i == 0) m /= i;
}
if (m > 1) ans = ans / m * (m - 1);
return ans;
}
龟速乘
ll _pow(__int128 a, __int128 b, __int128 mod) {
ll ans = 1;//注意是1不是0,不然23行是0*a
while (b) {
if (b & 1) ans = (ans * a) % mod;
a = a * a % mod;
b >>= 1;
}
return ans;
}
__int128是什么?有什么用?什么时候用?
在最大值比long long 大一点点时使用。
INT_MAX = 2^(32-1)-1
LONG_LONG_MAX = 2^(64-1)-1
__int128极大值:2^(128-1)-1
注:__int128只能进行四则运算,不能用cin,cout输出。
总结
本次考试总结
得分分布
题目序号 | 题目名称 | 得分 | 题目难度 |
---|---|---|---|
1 | 行走的机器人 robot | 100 | 中等 |
2 | 多米诺骨牌涂色 paint | 27 | 中等+ |
3 | 最小得分 mex | 0 | 中等+ |
4 | 幸运数字 lucky | 0 | 难 |
5 | 无向图与函数 grafun | 0 | 难 |
6 | 最小子集 subset | 11 | 难 |
反思
考试上的
1.还是有部分分该的没有得到,如第二题打表,情况考虑出现偏差,丢失:5-10分;
2.第四题的方法与题解上30pts的方法大同小异,丢失:50分,原因尚未找出(持续跟踪)。
学习上的
1.学过的知识不会举一反三,如第二题——递推。
2.知识面不宽,超前学习不够。如本系列第五题——图论,拿不到分,想有成绩上的突破就必须攻下它。
1.周赛系列第一、二题一般为模拟、递推或一些简单的算法。难度较低,目标得分:150+;
2.第三、四题多为更难的算法,如:DP、贪心、搜索等,目标得分:50+。
3.第五题考查知识点为图论,想要拿到此题的分就必须尽快学习图论的知识。
4.第六题一般为数论,难度极大,得分不易。