【算法入门赛】星码StarryCoding 入门教育赛 5题解

61 篇文章 0 订阅

比赛链接(可赛后补题):https://www.starrycoding.com/contest/11

在这里插入图片描述

A. a+b(easy)

由于 a a a b b b都是0到9之间的整数,则表达式的长度必定为3,所以直接将 a a a b b b提取出来计算即可。

代码

#include <bits/stdc++.h>
using namespace std;

void solve()
{
    string s;cin >> s;
    cout << (s[0] - '0') + (s[2] - '0') << '\n';
}

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

B. a+b(hard)

遍历表达式字符串,将 a a a b b b提取出来进行计算即可。

代码

#include <bits/stdc++.h>
using namespace std;
#define int long long

void solve()
{
	string s;cin >> s;
	int a = 0,b = 0;
	bool flag = true;
	for(auto &i : s)
	{
		if(i == '+')flag = false;
		else
		{
			if(flag)a = a * 10 + (i - '0');
			else b = b * 10 + (i - '0');
		}
	}
	
	cout << a + b << '\n';
}

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

C. 最近不存在数字

将数组 a a a中所有数字存入 s e t set set中(当然用 m a p map map等其他数据结构也可以),方便后续判断存在性。

枚举与 b b b的距离 i i i,先判断较小的 b − i b-i bi,再判断 b + i b+i b+i,若不存在于 a a a中就直接返回结果。

代码

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 1e5 + 9;
ll a[N];

void solve()
{
    ll n, b;
    cin >> n >> b;
    set<ll> st;
    for (int i = 1; i <= n; ++i)
    {
        ll x;
        cin >> x;
        st.insert(x);
    }
    for (int i = 0; i <= 1e5; ++i)
    {
        if (!st.count(b - i))
        {
            cout << b - i << '\n';
            return;
        }
        if (!st.count(b + i))
        {
            cout << b + i << '\n';
            return;
        }
    }
}

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

D. 数字根

我们将1~36写出来,
$
\begin{bmatrix}
1 & 2 & 3 & 4 & 5 & 6 & 7 & 8 & 9\
10 & 11 & 12 & 13 & 14 & 15 & 16 & 17 & 18\
19 & 20 & 21 & 22 & 23 & 24 & 25 & 26 & 27\
28 & 29 & 30 & 31 & 32 & 33 & 34 & 35 & 36\
\cdots \
\end{bmatrix}
$
我们发现同一列中的数字元素数字根都相同,所以我们推测数字根出现的规律大致是以9为一个周期递推,而事实也正是如此。所以我们要找第 k k k个数字根为 x x x的数字,也就是在上述矩阵中第 k k k行,第 x x x列的元素,所以答案为 ( k − 1 ) × 9 + x (k - 1) \times 9 + x (k1)×9+x

代码

#include <bits/stdc++.h>
using namespace std;
#define int long long

void solve()
{
	int k,x;cin >> k >> x;
	cout << (k - 1) * 9 + x << '\n';
}

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

E.再短一点

思路

长度为 m m m的二进制字符串 T T T是幸运的,当且仅当 m = 1 m = 1 m=1或( 1 < m 1 \lt m 1<m S [ m ] ≠ S [ m − 1 ] S[m] \neq S[m - 1] S[m]=S[m1])。

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

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

复杂性: O ( n ) \mathcal{O}(n) O(n)

代码

#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.更短一点

思路

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

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

证明:

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

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

00 … 00 ⏟ x   S   11 … 11 ⏟ y \underbrace{00 \ldots 00}_{x} \space S \space \underbrace{11 \ldots 11}_{y} x 0000 S y 1111

其中 S S 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;
}
  • 29
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值