Harbour.Space Scholarship Contest 2021-2022 (open for everyone, rated, Div. 1 + Div. 2) A-D题

本文详细解析了四道算法题目,涉及数字性质判断、字符串操作及决策模拟。A题讨论了数字末尾为9的特性;B题通过深度优先搜索解决字符串匹配问题;C题模拟了足球点球决胜过程,探讨了最优决策;D题考察了字符串处理,通过回溯法判断能否通过删除字符使两串相等。文章展示了清晰的思路和高效的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

A题

  • 函数S(n)S(n)S(n)表示nnn的各位数字之和,给出nnn,问[1,n][1,n][1,n]之间有多少数字满足S(n+1)<S(n)S(n+1)\lt S(n)S(n+1)<S(n)
  • 显然只有末尾数字是9的数才有这样的性质,这样的数个数是n+110\frac{n+1}{10}10n+1
int main(){
    int t, n;
    cin >> t;
    while(t--){
        cin >> n;
        cout << (n + 1) / 10 << "\n";
    }
    return 0;
}

B题

  • 先往右后往左,也可以不走,题意需要仔细理解,停下的时候字符也只算一遍,不是重复计算,用两个dfsdfsdfs搜索就行了,比赛时候忘了初始化怎么也过不去,吐了
  • 另外也积累了一个教训,函数传参别传stringstringstring,尤其是递归函数,会大大降低速度,因为会进行一次复制,可以通过传引用解决这个问题,或者稍微麻烦一点就写全局变量
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int INF = 0x3f3f3f3f;
const int MAXN = 1e6 + 100;
const double eps = 1e-6;
int Data[MAXN];
string x, y;
bool ok;
bool f;
void dfs(int i, int now){
    if(now >= y.length()){
        ok = true;
        return;
    }
    if(i >= x.length()) return;
    if(x[i] != y[now]) return;
    if(f) dfs(i + 1, now + 1);
    f = false;
    dfs(i - 1, now + 1);
}
int main(){
    int t;
    ios::sync_with_stdio(false);
    cin >> t;
    while(t--){
        cin >> x >> y;
        int len = x.length();
        ok = false;
        for(int i=0;i<len;i++){
            f = true;
            if(x[i] == y[0]){
                dfs(i, 0);
            }
        }
        cout << (ok ? "YES" : "NO") << "\n";
    }
    return 0;
}

C题

  • 模拟了一个足球比赛点球的情景,让你选择改变???,使得所需的点球次数最少,问最少需要几次
  • 我以为是谁1多让谁赢,实际上是错的,我又以为是1和???加起来谁多让谁赢,实际也不对,比如1?1?1?0?0?1?1?1?0?0?1?1?1?0?0?这个例子,因为就两种情况,要么1赢,要么2赢,分别求取然后取最小值就行了
  • 如果让1赢,要检查一下当1进球时候是否结束比赛,当2没进球时候是否结束比赛;如果让2赢,要检查一下当2进球时候是否结束比赛,当1没进球时是否结束比赛,这两种情况的剩余比赛场次是不同的
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int INF = 0x3f3f3f3f;
const int MAXN = 1e6 + 100;
const double eps = 1e-6;
int Data[MAXN];
int main(){
    int t;
    ios::sync_with_stdio(false);
    string x;
    cin >> t;
    while(t--){
        cin >> x;
        int a, b, ans1, ans2;
        a = b = ans1 = ans2 = 0;
        for(int i=0;i<10;i+=2){
            if(x[i] == '1' || x[i] == '?'){
                a++;
                ans1++;
                if((10 - i) / 2 + b < a) break;
            }else ans1++;
            if(x[i + 1] == '1'){
                b++;
                ans1++;
            }else{
                ans1++;
                if((8 - i) / 2 + b < a) break;
            }
        }
        a = b = 0;
        for(int i=0;i<10;i+=2){
            if(x[i] == '1'){
                a++;
                ans2++;
            }else{
                ans2++;
                if((8 - i) / 2 + a < b) break;
            }
            if(x[i + 1] == '1' || x[i + 1] == '?'){
                ans2++;
                b++;
                if((8 - i) / 2 + a < b) break;
            }else{
                ans2++;
            }
        }
        cout << min(ans1, ans2) << "\n";
    }
    return 0;
}

D题

  • 题目的意思是输入两串字符串,将第一串的任意位置字符换成backspacebackspacebackspace删除前一个字符,问能不能达到第二个串
  • 赛后我找到touristtouristtourist大神的本题程序,想看看为什么他能在这么快的时间内切掉这题,结果发现他的代码非常的清爽,思路也是格外的清奇,实在是吾辈楷模
  • 从两串字符串后面向前看,因为如果第二串的最后一个字符在第一串后面没出现,那么这个字符肯定要被删除,且会连带它前面的字符一起被删掉,这样不停地寻找匹配的字符直到全部匹配即可
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int INF = 0x3f3f3f3f;
const int MAXN = 1e6 + 100;
const double eps = 1e-6;
int Data[MAXN];
int main(){
    int t;
    ios::sync_with_stdio(false);
    string x, y;
    cin >> t;
    while(t--){
        cin >> x >> y;
        int n = x.length();
        int m = y.length();
        int i = n - 1;
        bool ok = true;
        for(int j=m-1;j>=0;j--){
            while(i >= 0 && x[i] != y[j]){
                i -= 2;
            }
            if(i < 0){
                ok = false;
                break;
            }
            i--;
        }
        cout << (ok ? "YES" : "NO") << '\n';
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Clarence Liu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值