T1 文景路上的红绿灯

难度:知道数学中周期的概念,然后简单条件判断即可。如果实在搞不清楚的,也可以直接用循环模拟处理。

算法:数学。

子任务 113030 分):只有红灯,输出 redred 就好。

子任务 223030 分):没有黄灯,只有红灯和绿灯,每个周期只有两种颜色了,处理起来会方便一点(其实也差不多)。

子任务 334040 分):循环模拟的做法略,第一题咱不考虑高阶语法的做法。首先可以算出每个周期的长度 t=x+y+z+y。这题主要目的就是给大家强化从 00 开始和从 11 开始的区别。可以先把 1q1∼q 分钟通过减 11 转换到 0q10∼q−1,然后通过 modtmod t 就可以得到第一个周期的结果,然后再加 11 就可以从 0t10∼t−1 转换回 1t1∼t 了。当然也可以一开始就给 qq 减少 11,然后每个灯的时间看成 0x10∼x−1 是红灯、xx+y1x∼x+y−1 是黄灯,以此类推。

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 不太随机的随机数列

难度:打表找规律!

算法:枚举。

子任务 113030 分):xx 非常小,把死循环改成循环执行 xx 次,然后只在第 xx 次输出即可。

子任务 223030 分):虽然 10910^9 很大,但是这里是等于号,也就是告诉了大家测试点的输入,所以不需要实时算出这一项,自己在本地跑出来结果后,当 x=109x=10^9 时直接输出答案就好。

子任务 334040 分):子任务 22 主要就是提醒大家可以本地打表,如果你执行上面的代码输出前 100100 项,很容易发现中间会出现循环的结果。前两项分别是 3333 和 157157,第 33 项是 184184 而第 3131 项也是 184184,所以 3303∼30 是一个周期,周期长度为 T=30−3+1。去掉前两项之后的 x2x−2 项就是每 tt 个数是一样的,直接按照类似于第一题的方式处理即可。这样能把数据缩小到 3030 以内,直接用子任务 11 的方式处理即可。

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 假装在洗一副扑克牌

难度:简单的字符串处理。

算法:字符串处理,枚举。

子任务 113030 分):只有一张牌,原样输出即可。

子任务 223030 分):没有 1010,那就是逆序输出字符串。

子任务 334040 分):逆序输出时遇到 0101 就输出 1010 即可。下面给出常规做法之外,另外再给出一个有趣的递归形式。

参考代码:

在遇到 s.size()-1 的形式时大家需要注意,s.size() 的返回值是无符号整型,所以当字符串为空、s.size()00 时,减一就会变成无符号整型的最大值。所以建议如果要减 11 就习惯性改成 int 后再处理。(当然这题的字符串长度保证大于等于 11,所以倒也无所谓了)

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 可持久化入门之数对

难度:主要难度在于读题,读题搞定后,就是一个简单的模拟题了。

算法:模拟。

子任务 113030 分):因为只有操作 22,没有修改,所以每个版本的两个数都一样。每次询问时根据 loc iloc i 来决定输出 xx 还是 yy 即可。

子任务 223030 分):因为操作的数只有第一个数,所以就是个一维数组的模拟了。每次先 a[i] = a[vi]; 复制一份,然后看看是改还是输出就好。

子任务 334040 分):在子任务 22 的基础上,从维护一个数改成维护两个数就好。每次操作前先复制一份,然后处理当前数对即可。

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;
}

0 comments

No comments so far...