Codeforces Round 964 (Div. 4) A - D 详细题解(Python,C++)--来自预备绿名选手的独特思维

        很好的比赛,让我大脑宕机,比赛题目还是很友好的,适合我这种基础不怎么好的 

        (什么queueforces,我知道参加的人多,但是你从7号下午四点多一直system test到9点才跑到66%,想提交都不行,所以题解拖的有点晚了)

最近找到一个很好的网站,可以看codeforces中的各种数据,就在这个文章中分享一下:

Codeforces Visualizer (cfviz.netlify.app)

比赛链接:

Dashboard - Codeforces Round 964 (Div. 4) - Codeforces

题A:

Problem - A - Codeforces

题目大意解析:

输入一个两位数,求各个位数的和,
比如输入77
输出14

思路:

获得一个数字的个位数就 % 10, 获得第一位就 / 10,输入的是两位数,也不需要管其他的

代码(C++):
 

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
    int tt;
    cin >> tt;
    while (tt--){
        int n;
        cin >> n;
        int res = n / 10 + n % 10;
        cout << res << '\n';
    }
}

代码(Python):

def main():
    t = II()
    res = []
    for _ in range(t):
        n = II()
        r = n % 10 + n // 10
        res.append(r)
    
    for r in res:
        print(r)

题B:

Problem - B - Codeforces

题目大意解析:

每个测试用例输入一行,一行总共4个数字

前面两个数表示第一个人的两张牌,后两个数表示第二个人的两张牌

现在比赛规则是:

两个人都随机翻开一张牌进行比大小,如果大于就获胜,如果等于就平局

一共两局,一方赢的次数大于另一方就获胜

输出第一个人赢的可能局数

思路:

这题很容易漏掉一种情况,就是1 : 0 的情况也算赢

然后暴力枚举即可,把每一种情况枚举出来,如果第一个人赢的次数严格大于第二个人
结果就加一

优化:每一种情况有两次对比的可能,所以最后只需要枚举两次就行,满足条件答案就加等于2

(比赛的时候,示例1 :0这种情况没给出来,让我wa了,我还是太菜了)

代码(C++):

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
    int tt;
    cin >> tt;
    while (tt--){
        int a1, a2, b1, b2;
        cin >> a1 >> a2 >> b1 >> b2;
        //赢的局数
        int x1 = 0, x2 = 0, res = 0;
        x1 = (a1 > b1) + (a2 > b2);
        x2 = (a1 < b1) + (a2 < b2);
        if (x1 > x2){
            res += 2;
        }
        x1 = (a1 > b2) + (a2 > b1);
        x2 = (a1 < b2) + (a2 < b1);
        if (x1 > x2){
            res += 2;
        }
        cout << res << '\n';
    }
}

代码(Python):

题C:

Problem - C - Codeforces

最近在刷洛谷,刷到一个很类似的题目,好吧也不是那么相似
P1047 [NOIP2005 普及组] 校门外的树 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

标的是入门题,但是不简单

题目大意解析:

看起来挺唬人的,还弄一个图,实际说的事情很简单
每个测试第一行输入三个数字n, s, m,n表示他一天计划的个数,s表示他洗澡的时间,m表示一天的分钟数目

接下来n行输入每个所用的区间,在计划时间内是无法洗澡的
求他这一天是否有时间洗澡,就是在[0, m]这个区间内,有几个区间被占满,看是否有一段长度为s的区间

思路:

首先他这个输入不是排序好的,首先按照区间左端点排序一遍,然后枚举从0到m是否存在长度大于s即可
具体方法就是从1开始遍历区间集合,然后先用第一个左端点减0,看是否大于等于s,然后往后遍历,用下一个区间的左端点减这个区间的右端点(有点像滑动窗口?(bushi))
然后最后用m减去最后一个区间有端点。

在这个过程看查看是否有一段是大于等于s的

代码(C++):

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    int t;
    cin >> t;
    while (t--) {
        int n, s, m;
        cin >> n >> s >> m;

        vector<pair<int, int>> arr(n);
        for (int i = 0; i < n; i++) {
            int x1, x2;
            cin >> x1 >> x2;
            arr[i] = {x1, x2};
        }
        // 对arr的第一列进行排序
        sort(arr.begin(), arr.end());
        int x = 0;
        int cur = arr[0].first;
        if (cur >= s) {
            x = 1;
        }
        for (int i = 1; i < n; i++) {
            cur = arr[i].first - arr[i - 1].second;
            if (cur >= s) {
                x = 1;
            }
        }
        if (m - arr[n - 1].second >= s) {
            x = 1;
        }
        if (x) {
            cout << "YES" << '\n';
        } else {
            cout << "NO" << '\n';
        }
    }
    return 0;
}

代码(Python):

def main():
    t = II()
    res = []
    for _ in range(t):
        n, s, m = MII()
        arr = []
        for i in range(n):
            x1, x2 = MII()
            arr.append([x1, x2])
        #可直接对arr的第一列进行排序
        arr.sort()
        x = 0
        cur = arr[0][0]
        if cur >= s:
            x = 1
        for i in range(1, len(arr)):
            cur = arr[i][0] - arr[i - 1][1]
            if cur >= s:
                x = 1
        if m - arr[n - 1][1] >= s:
            x = 1
        if x:
            res.append("YES")
        else:
            res.append("NO")
 
    for r in res:
        print(r)

题D:

Problem - D - Codeforces

题目大意解析:

题目意思很简单,不要想多就好了(我第一开始还想怎么dp,属于脑子抽了)
第一行输入一个字符串s
第一行输入一个字符串t
字符串s中包含?这个字符,现在可以把?变成任意一个字符,寻找是否可以让s变换成拥有t的子序列(可以不连续)

如果可以就输入YES,然后输出一个满足条件的变换后的字符串s
如果不行就输入NO

思路:

不要多想,想简单一点
进行字符串匹配就可以了

同时遍历两个字符串中的字符
如果此时字符串s和t中字符相同的,就往后遍历
如果不相同,就字符串s往后遍历

如果遍历到s中的?,就把问号变成此时字符串t中的字符
然后往后遍历
最后把多余的问号随便变成一个字母就行
(算是贪心?感觉没有严格的证明)

思想就是碰到?就直接修改即可,如果s遍历完了,t还没遍历完,那就无法满足条件

代码(C++):

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    int t;
    cin >> t;
    while (t--) {
        string s;
        cin >> s;
        string t;
        cin >> t;
        int x1 = 0, x2 = 0;
        while (x2 < t.length() && x1 < s.length()) {
            if (s[x1] == t[x2]) {
                x1++;
                x2++;
            } else {
                if (s[x1] == '?') {
                    s[x1] = t[x2];
                    x1++;
                    x2++;
                } else {
                    x1++;
                }
            }
        }
        if (x2 == t.length()) {
            cout << "YES" << '\n';
            for (int i = 0; i < s.length(); i++) {
                if (s[i] == '?') {
                    s[i] = 'a';
                }
            }
            cout << s << '\n';
        } else {
            cout << "NO" << '\n';
        }
    }
    return 0;
}

代码(Python):

def main():
    t = II()
    res = []
    for _ in range(t):
        s = I()
        s = list(s)
        t = I()
        x1, x2 = 0, 0
        while x2 < len(t) and x1 < len(s):
            if s[x1] == t[x2]:
                x1 += 1
                x2 += 1
            else:
                if s[x1] == "?":
                    s[x1] = t[x2]
                    x1 += 1
                    x2 += 1
                else:
                    x1 += 1
                    
        if x2 == len(t):
            res.append("YES")
            for i in range(len(s)):
                if s[i] == "?":
                    s[i] = "a"
            res.append("".join(s))
        else:
            res.append("NO")
 
    for r in res:
        print(r)

题E:

Problem - E - Codeforces

题目大意解析:

输入两个数字l, r
这两个数字表示黑板上有l到r(包括l 和 r)的所有整数

操作是:
现在可以选择任意两个数x, y,擦去后在相同的位置写下 3x 和 y / 3(向上取整)

输出最小操作次数,使得所有数字为0

看题目最下面的Note就好理解了

思路:

数学题,有点没想明白,贴个c++代码

代码(C++):

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	int t;
	cin >> t;
	while (t--) {
		int l, r;
		cin >> l >> r;
		r++;
		int res = 0;
		int x = l;
		while (x > 0) {
			res += 2;
			x /= 3;
		}
		l++;
		int t = 1, i = 1, j = 3;
		while (i <= r) {
			int c = min(j, r) - max(i, l);
			if (c >= 0){
				res += c * t;
			}
			t++;
			i *= 3;
			j *= 3;
		}
		cout << res << '\n';
	}
}

感觉这次div4很简单的,某些群聊里面也把这次比赛称作div5,但我脑子可能抽了,其实还是练少了,比如第二题wa,看了半天不知道哪里错了,最后才想起来,然后第四题,本来很简单的,我又想多了,用复杂方法写半天,基础还是有点差,训练量得再加

  • 20
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值