- 西中经开联校 - 第 7 场周赛
【题解】西中经开联校 - 第 7 场周赛
- @ 2025-1-19 10:58:07
T1 文景路上的红绿灯
难度:知道数学中周期的概念,然后简单条件判断即可。如果实在搞不清楚的,也可以直接用循环模拟处理。
算法:数学。
子任务 ( 分):只有红灯,输出 就好。
子任务 ( 分):没有黄灯,只有红灯和绿灯,每个周期只有两种颜色了,处理起来会方便一点(其实也差不多)。
子任务 ( 分):循环模拟的做法略,第一题咱不考虑高阶语法的做法。首先可以算出每个周期的长度 t=x+y+z+y。这题主要目的就是给大家强化从 开始和从 开始的区别。可以先把 分钟通过减 转换到 ,然后通过 就可以得到第一个周期的结果,然后再加 就可以从 转换回 了。当然也可以一开始就给 减少 ,然后每个灯的时间看成 是红灯、 是黄灯,以此类推。
C++ 代码:
#include <bits/stdc++.h>
using namespace std;
int main()
{
int x, y, z, q;
cin >> x >> y >> z >> q;
int t = x + y + z + y;
q = (q - 1) % t + 1;
if (q <= x)
cout << "red";
else if (q <= x + y)
cout << "yellow";
else if (q <= x + y + z)
cout << "green";
else
cout << "yellow";
return 0;
}
T2 不太随机的随机数列
难度:打表找规律!
算法:枚举。
子任务 ( 分): 非常小,把死循环改成循环执行 次,然后只在第 次输出即可。
子任务 ( 分):虽然 很大,但是这里是等于号,也就是告诉了大家测试点的输入,所以不需要实时算出这一项,自己在本地跑出来结果后,当 时直接输出答案就好。
子任务 ( 分):子任务 主要就是提醒大家可以本地打表,如果你执行上面的代码输出前 项,很容易发现中间会出现循环的结果。前两项分别是 和 ,第 项是 而第 项也是 ,所以 是一个周期,周期长度为 T=30−3+1。去掉前两项之后的 项就是每 个数是一样的,直接按照类似于第一题的方式处理即可。这样能把数据缩小到 以内,直接用子任务 的方式处理即可。
C++ 代码:
#include <bits/stdc++.h>
using namespace std;
// 1:33 2:157 3:184 ... 30:76 31:184
const int t = 30 - 3 + 1;
int main()
{
long long x;
cin >> x;
if (x > 2)
{
long long partA = 2;
long long partB = x - 2;
partB = (partB - 1) % t + 1;
x = partA + partB;
}
int seed = 33;
for (int i = 1; i <= x; i++)
{
if (i == x)
cout << seed << '\n';
seed = seed * seed % 233;
}
return 0;
}
T3 假装在洗一副扑克牌
难度:简单的字符串处理。
算法:字符串处理,枚举。
子任务 ( 分):只有一张牌,原样输出即可。
子任务 ( 分):没有 ,那就是逆序输出字符串。
子任务 ( 分):逆序输出时遇到 就输出 即可。下面给出常规做法之外,另外再给出一个有趣的递归形式。
参考代码:
在遇到 s.size()-1 的形式时大家需要注意,s.size() 的返回值是无符号整型,所以当字符串为空、s.size() 为 时,减一就会变成无符号整型的最大值。所以建议如果要减 就习惯性改成 int 后再处理。(当然这题的字符串长度保证大于等于 ,所以倒也无所谓了)
C++ 代码 1:
#include<bits/stdc++.h>
using namespace std;
string a;
int n;
int main()
{
cin >> a;
n = a.size();
for (int i = n - 1; i >= 0; i -- )
{
if (a[i] == '0' && a[i - 1] == '1')
{
cout << 10;
i -- ;
}
else cout << a[i] ;
}
return 0;
}
C++ 代码 2:
#include <bits/stdc++.h>
using namespace std;
string s;
void f(int l, int r)
{
if (l > r)
return;
if (s[l] == '1')
{
f(l + 2, r);
cout << "10";
}
else
{
f(l + 1, r);
cout << s[l];
}
}
int main()
{
cin >> s;
f(0, (int)s.size() - 1);
return 0;
}
T4 可持久化入门之数对
难度:主要难度在于读题,读题搞定后,就是一个简单的模拟题了。
算法:模拟。
子任务 ( 分):因为只有操作 ,没有修改,所以每个版本的两个数都一样。每次询问时根据 来决定输出 还是 即可。
子任务 ( 分):因为操作的数只有第一个数,所以就是个一维数组的模拟了。每次先 a[i] = a[vi]; 复制一份,然后看看是改还是输出就好。
子任务 ( 分):在子任务 的基础上,从维护一个数改成维护两个数就好。每次操作前先复制一份,然后处理当前数对即可。
C++ 代码:
#include <bits/stdc++.h>
using namespace std;
int M;
int a[105][3];
int main()
{
cin >> M;
cin >> a[0][1] >> a[0][2];
for (int i = 1; i <= M; i ++ )
{
int v, op, loc, val;
cin >> v >> op;
a[i][1] = a[v][1];
a[i][2] = a[v][2];
if (op == 1)
{
cin >> loc >> val;
a[i][loc] = val;
}
if (op == 2)
{
cin >> loc;
cout << a[i][loc] << endl;
}
}
return 0;
}