星码StarryCoding 入门教育赛 5

这次我第五十分钟的时候才想起来得做题,一共就九十分钟,服了。

A:a+b(easy)

题目描述

给定一个形式为a+b的表达式,其中a和b是0到9的一个整数,您需要对其进行求值并打印结果。

输入格式

第一行包含一个整数T(1≤T≤1000),表示测试样例组数。
接下来T行每行一个表达式。

输出格式

为每个表达式求值并打印结果。

输入样例

4
4+2
0+0
3+7
8+9

输出样例

6
0
10
17

解题思路:

直接写。

#include <iostream>
#include <string>
using namespace std;
int main() {
    int T;
    cin >> T; 
    while (T--) {
        string expression;
        cin >> expression;
        int a = expression[0] - '0';
        int b = expression[2] - '0'; 
        int result = a + b;
        cout << result << endl; 
    }
    return 0;
}

B:a+b(hard)

题目描述

本题为A的hard版本,与easy版本的唯一区别在于a和b的范围不同。
给定一个形式为a+b(0≤a,b≤1014)的表达式,您需要对其进行求值并打印结果。

输入格式

第一行包含一个整数T(1≤T≤1000),表示测试样例组数。
接下来T行每行一个表达式。

输出格式

为每个表达式求值并打印结果。

输入样例 

4
4+2
0+0
3+7
8+9

输出样例

6
0
10
17

解题思路:

因为这个是ACM赛制,所以说,要考虑时间复杂度,但是就是long long类型来定义也是远远不够的,事实上,遇到这种显然无法直接表示的运算时,通常就是采用字符串的方法来解决,核心就是字符与数字的转换。

#include <iostream>
#include <string>
using namespace std;
string addLargeNumbers(string num1, string num2) {
    if (num1.length() < num2.length()) {
        swap(num1, num2);
    }
    int carry = 0;
    int n1 = num1.length(), n2 = num2.length();
    string result = "";
    for (int i = 0; i < n1; ++i) {
        int sum = (num1[n1 - 1 - i] - '0') + (i < n2 ? num2[n2 - 1 - i] - '0' : 0) + carry;
        carry = sum / 10;
        result = to_string(sum % 10) + result;
    }
    if (carry) {
        result = to_string(carry) + result;
    }
    return result;
}
int main() {
    int T;
    cin >> T;
    while (T--) {
        string expression;
        cin >> expression;
        size_t pos = expression.find('+');
        string num1 = expression.substr(0, pos);
        string num2 = expression.substr(pos + 1);
        string result = addLargeNumbers(num1, num2);
        cout << result << endl;
    }
    return 0;
}

C:最近不存在数字

题目描述

给定长度为n的数组a和一个整数b。

要求找出一个整数x满足:

  • x∈/a,即x不存在于数组a中。
  • ∣b−x∣最小。

若有多个x满足条件,取较小的x作为答案。

输入格式

注意:本题有多组测试样例!

第一行一个整数T表示测试用例个数。(1≤T≤10)

对于每组测试用例:

一行两个整数n,b(1≤n≤105,1≤b≤109)。

第二行n个整数表示ai​(1≤ai​≤109)。

数据保证:∑n≤2×105

输出格式

对于每组测试用例,输出一个整数表示答案。

输入样例

2
3 5
2 3 4
4 7
7 10 6 8

输出样例

5
5

解题思路:

这个题翻译一下,如果b不在数组a中,那么直接输出b,如果b这个数字位于a中,那就在数组中寻找一个与b差值最小的数字,并且取最小的那个,初始化 ans 为 b,表示最初的答案设定为 b。
初始化 minDiff 为一个较大的值 INT_MAX,用来存储当前最小的差距。遍历 -1、0、1 这三个相对于 b 的偏移量,对应着 b-1、b、b+1 这三个候选数。对于每个候选数,如果它在数组 a 中存在,则向下一个数移动,直到找到数组 a 中不存在的数。计算当前候选数与 b 的差距,并更新 minDiff 和 ans,以确保找到最接近 b 的且不在数组 a 中的数。核心思想是通过迭代 b-1、b、b+1 这三个数,找到在数组 a 中不存在的最接近 b 的数,并且保证在距离相等时选择较小的数。

#include <iostream>
#include <vector>
#include <set>
#include <cmath>
#include<climits>
using namespace std;
int main() {
    int T;
    cin >> T;
    while (T--) {
        int n, b;
        cin >> n >> b;
        set<int> a;
        for (int i = 0; i < n; ++i) {
            int num;
            cin >> num;
            a.insert(num);
        }
        int ans = b;
        int minDiff = INT_MAX;
        for (int i = -1; i <= 1; ++i) {
            int candidate = b + i;
            while (a.find(candidate) != a.end()) { 
                candidate += (i >= 0) ? 1 : -1; 
            }
            int currentDiff = abs(b - candidate);
            if (currentDiff < minDiff || (currentDiff == minDiff && candidate < ans)) {
                minDiff = currentDiff;
                ans = candidate;
            }
        }
        cout << ans << endl;
    }
    return 0;
}

D:数字根

题目描述

非负整数的数字根是通过不断迭代对数字的每一位求和,直到得出一个一位数为止,这个一位数就是它的数字根。例如5的数字根是5,而38的数字根是2,求解过程如下:38→3+8=11→1+1=2。
现在阿慧得到了一个作业,要求找出第k个数字根为x的数字,但是她不会,所以请教了你来帮她解决这个麻烦。

输入描述

第一行一个整数T(1≤T≤1000),表示测试样例组数。
接下来T行,每行两个整数k,x(1≤k≤1012,1≤x≤9)。

输出描述

为每个测试样例打印一个整数,表示第𝑘k个数字根为x的整数。

输入样例

3
1 5
5 2
3 1

输出样例

5
38
19

解题思路:

我们将1~36写出来,

我们发现同一列中的数字元素数字根都相同,所以我们推测数字根出现的规律大致是以9为一个周期递推,而事实也正是如此。所以我们要找第𝑘k个数字根为𝑥x的数字,也就是在上述矩阵中第𝑘k行,第𝑥x列的元素,所以答案为(k−1)×9+x。

#include <iostream>
using namespace std;
void solve()
{
	int k,x;
    cin >> k >> x;
	cout << (k - 1) * 9 + x << '\n';
}

int main()
{
	int t;
    cin >> t;
	while(t--)
      solve();
    return 0;
}

E:再短一点

题目描述

当一个长度为m的二进制字符串T是幸运的,我们可以通过任意顺序执行以下两种操作m−1来获得长度为1的字符串:

  • 选择T中任意等于01的子字符串,将其替换为1。

  • 选择T中任何等于10的子字符串,然后将其替换为0。

例如,如果T=001,我们可以选择子字符串[T2​T3​]并执行第一个操作。得到T=01。

您将得到一个长度为n的二进制字符串S,索引从1到n。找出(l,r)(1≤l≤r≤n)使得S[l…r](S从l到r的子字符串)是一个幸运的字符串的整数对的个数。

输入描述

第一行包含一个整数t(1≤t≤1000)—测试用例的数量。下面是测试用例的描述。

每个测试用例的第一行包含一个整数n(1≤n≤2⋅105)——大小为S。

每个测试用例的第二行包含一个由n字符S1​S2​…Sn​组成的二进制字符串S。(每个1≤i≤n对应Si​= 0或Si​= 1)

保证所有测试用例的n之和不超过2⋅105。

输出描述

对于每个测试用例,输出使S[l…r](S从l到r的子字符串)为偏执字符串的整数对(l,r)1≤l≤r≤n的个数。

输入样例1

5
1
1
2
01
3
100
4
1001
5
11111

输出样例1

1
3
4
8
5

样例解释

在第一个示例中,S已经具有长度1,不需要任何操作。

在第二个示例中,S的所有子字符串都是幸运的。对于整个字符串,执行第一个操作就足够了。

在第三个示例中,除了[S2​S3​]之外,S的所有子字符串都是幸运的,因为我们不能对它和[S1​S2​S3​](整个字符串)执行任何操作。

解题思路:

长度为m的二进制字符串T是幸运的,当且仅当m=1或(1<m和𝑆[𝑚]≠𝑆[𝑚−1])。

  • 在S[m−1]=S[m]的情况下:我们永远不能删除最后两个字符,因为它们将始终保持相等。所以 S 不是幸运的。
  • 在𝑆[𝑚−1]≠𝑆[𝑚]的情况下:如果m=2,我们可以通过一次操作达到我们的目标。否则,假设最后一个字符为0。现在最后三个字符不是010就是110。在第一种情况下,对[Sm−2​,Sm−1​]执行操作,在第二种情况下,对 [Sm−1​,Sm​] 执行操作。然后最后两个字符将是10,我们可以在新的字符串上继续这个算法,直到我们得到m=1。

长度为1的幸运的子字符串的个数等于n。为了计算更长的子字符串的个数,我们可以将索引2中的r固定为n。如果𝑆[𝑟]≠𝑆[𝑟−1]成立,我们应该在答案上加上r−1。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5 + 9;
void solve()
{
    int n; cin >> n;
    ll ans = n;
    string s; cin >> s;
    for(int i = 1; i < n; ++i)
    {
        if(s[i] != s[i - 1]) ans += i;
    }
    cout << ans << '\n';
}
int main()
{
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    int _; cin >> _;
    while(_ --)solve();
	return 0;
}

F:更短一点

题目描述

小小的也很可爱呢......

Piper有一串长度为n的二进制字符串s(即字符串只由0和1组成)。Piper觉得这串字符串不可爱,他想让它变得更可爱一点,但同时又希望它可爱地有内涵一点,所以Piper决定用一种特殊的方式让它变得可爱。

选择两个连续的字符si​和si+1​,如果si​是1,si+1​是0,他就可以擦除其中的1个字符(他可以选择擦除哪一个,但不能同时擦除两个字符)。擦除后字符串会更加地可爱!。

Piper可以进行任意数量的擦除(可能是零),他想让字符串s尽可能可爱。他认为对于两个不同的字符串x和y,的字符串更可爱,如果它们的长度相同,那么从词典上看更小的字符串更可爱。

小提示:如果我们有两个长度相同的字符串x和y,那么如果有一个位置i是x1​=y1​、x2​=y2​、...、xi−1​=yi−1​和xi​<yi​,那么x在词法上比y小。

请打印Piper在操作过后能得到的最可爱的字符串。

输入描述

第一行包含整数t(1≤t≤104) - 测试用例数。

接下来的2t行包含测试用例--每两行一个。

每个测试用例的第一行包含整数n(1≤n≤105) - 字符串s的长度。

第二行包含二进制字符串s。字符串s是长度为n的字符串,仅由 0 和 1 组成。

保证测试用例中n的总和不超过105。

输出描述

打印t个答案--每个测试用例一个。

i-th 测试用例的答案是李在做了一定数量的操作(可能是零)后能得到的最可爱的字符串。

输入样例

5
10
0001111111
4
0101
8
11001101
10
1110000000
1
1

输出样例

0001111111
001
01
0
1

样例解释

在第一个测试用例中,Piper不用执行任何动作。

在第二个测试用例中,Piper应该擦除 s2​ 。

例如,在第三个测试用例中,Piper可以按照以下顺序下棋:11001101 →→ 1100101 →→ 110101 →→ 10101 →→ 1101 →→ 101 →→ 01。

解题思路:

已知我们无法对非降序的字符串进行操作。

操作的条件:前1后0。所以猜想:对于一串以1开头,以0结尾的子串都可以被擦除至剩一个0。

证明:

对于一串以1开头的字符串,从前往后删0,我们总能得到一串不包含0的字符串,这很容易。现在保留末尾的0,再从后往前删掉所有的1。显然是可取的。

于是我们得到结论,对于一串以1开头,以0结尾的子串都可以被擦除至剩一个0。而由于我们无法对非降序的字符串进行操作,所以答案的构成我们可以视作:

其中𝑆S为一串以1开头,以0结尾的子串。必然是这样的,如果在最前面加上一个1,那么不妨把中间子串的左边界扩至开头来保持结构;在末尾加0也是同理。

于是我们只要找第一个1,再找末尾一个0,将这两个位置及其中间的字符都替换为0即可。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5 + 9;

void solve()
{
    int n; cin >> n;
    string s; cin >> s;
    int l = -1, r = -1;
    int flag = 1;
    for(int i = 0; i < n; ++i)
    {
        if(s[i] == '1' && flag)
        {
            l = i;
            flag = 0;
        }
        if(s[i] == '0' && !flag)
        {
            r = i;
        }
    }
    if(l != -1 && r != -1)
    {
        for(int i = 0; i < l; ++i) cout << s[i];
        for(int i = r; i < n; ++i) cout << s[i];
        cout << '\n';
    }
    else cout << s << '\n';
}

int main()
{
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    int _; cin >> _;
    while(_ --)solve();
	return 0;
}

最近动了个小手术,会停止更新一段时间,请谅解

  • 19
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值