星码StarryCoding 入门教育赛4

这是一个我关注的算法爷所举办的比赛,对于我来说,也有一定的经验丰收,通过做这些题可以加强自己的思维能力。

A:小朋友过马路

题目描述

有n个小朋友排成一排过马路,第i个小朋友身高为ai​, 小e想知道有多少个小朋友比身边的两个小朋友都严格地高。

输入格式

第一行一个整数T(1≤T≤1000)表示样例个数。

对于每一个样例:

第一行两个整数n(1≤n≤105)。

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

数据保证∑n≤2×105

输出格式

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

输入样例

2
3
1 2 1
5
1 2 1 3 2

输出样例

1
2

 解题思路:

这个题属于签到题,我们只需要按照题目说的意思去做就行了,严格高于意思就是不能是等于,必须是大于,这点需要注意。

#include <iostream>
#include <vector>
using namespace std;
int main() {
    int T;
    cin >> T;
    while (T--) {
        int n;
        cin >> n;
        vector<int> a(n);
        for (int i = 0; i < n; ++i) {
            cin >> a[i];
        }
        int count = 0;
        for (int i = 1; i < n - 1; ++i) {
            if (a[i] > a[i - 1] && a[i] > a[i + 1]) {
                count++;
            }
        }

        cout << count << endl;
    }

    return 0;
}

 B:平衡出题

题目描述

你是StarryCoding一场比赛的出题者,你准备了n个问题,其中第i个问题的难度为ai​。你将进行以下流程:

· 从列表中删除一些问题(可能是零个)

· 将剩下的问题按任意顺序重新排序

当且仅当任意两个连续问题的难度之差的绝对值小于等于𝑘k时,这场比赛才算平衡。
为了使问题的排序达到平衡,你至少需要删除多少个问题?

输入格式

第一行包含一个整数 t(1≤t≤1000) 表示测试用例数量。

每个测试用例的第一行包含两个正整数 n(1≤n≤2×105) 和 k(1≤k≤109) 表示问题数和连续问题之间允许的最大绝对差值。

每个测试用例的第二行包括 n 个空格分隔的整数 ai​(1≤ai​≤109) 表示每个问题的难度

输出格式

对于每个测试用例,输出一个整数,表示为使问题平衡,你必须删除的最小问题数

输入样例

7
5 1
1 2 4 5 6
1 2
10
8 3
17 3 1 20 12 5 17 12
4 2
2 4 6 8
5 3
2 3 19 10 8
3 4
1 10 5
8 1
8 3 1 4 5 10 7 3

输出样例

2
0
5
0
3
1
4

解题思路:

这个题,我们可以这么想:先给这个数组排序,排好序之后,有单调性,然后我们求其最长的能够符合要求的子序列,再用数组元素总数减去子序列的长度,就可以得到答案,所以这个问题的指向就为:如何求出符合要求的最长子序列?

设置maxlength代表最长,currentlength为目前长度,从第二个元素开始循环,因为第一个元素是没有讨论的必要的,符合要求currentlength就加一,不符合,就开始判断,maxlength取值为它与currentlength中最长的那一个,currentlength归一,一切重来,最后得到最长,再相减即可。

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
    int t;
    cin >> t;
    while (t--) {
        int n, k;
        cin >> n >> k;
        vector<int> a(n);
        for (int i = 0; i < n; ++i) {
            cin >> a[i];
        }
        sort(a.begin(),a.end());
        int max_length = 1;
        int current_length = 1;
        for (int i = 1; i < n; ++i) {
            if (abs(a[i] - a[i - 1]) <= k) {
                current_length++;
            } else {
                max_length = max(max_length, current_length);
                current_length = 1;
            }
        }
        max_length = max(max_length, current_length);

        int min_deletions = n - max_length;
        cout << min_deletions << endl;
    }

    return 0;
}

C:这是啥数?

题目描述

给定一个由 n 个元素组成的数组 𝑎 ,求数组在执行下列操作 任意次 后的最大和:

输入格式

输入由多个测试用例组成。第一行包含一个整数 T (1≤T≤1000) - 测试用例的数量。测试用例说明如下:

每个测试用例的第一行都包含一个整数 n (2≤n≤2⋅105) - 数组的长度。

下一行包含 n 个空格分隔的整数 a1​,a2​,…,an​ (−109≤ai​≤109) 。

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

输出格式

对于每个测试用例,输出数组在执行所述操作任意次数后可能具有的最大和。

输入样例

5
3
-1 -1 -1
5
1 5 -5 0 2
3
1 2 3
6
-1 10 9 8 7 6
2
-1 -1

输出样例

1
13
6
39
2

 解题思路:

无论进行多少次操作,负数个数的奇偶性都不会改变。(基本规则)

如果负数的个数是偶数 ,最大值就是所有数字的绝对值之和,因为负数个数的奇偶性是不会改变的,那么我们通过若干次变换,总能得到负数个数为0的数组。

如果负数的个数是奇数 ,那么若干次变换后最后一定有一个负数。我们将选择绝对值最小的一个,其余的保持正数(为简单起见,我们将 0 视为负数)

#include<iostream>
#include<vector>
using namespace std;
int main()
{
    int T;
    cin >> T;
    while(T --)
    {
       int n;
       cin>>n;
       vector<int> a(n);
       for(auto &x : a) 
         cin >> x;
       int ans = 0, cnt = 0, mi = 9999;
       for(auto &x : a)
       {
          if(x < 0)
          {
            cnt ++;
            x = -x;
          }
          ans += x;
          mi = min(mi, x);
       }
          cout << (cnt & 1 ? ans - 2 * mi : ans) <<endl;
    }
    return 0;
}

D:公平数

题目描述

如果一个正整数能被它的每个位上的非零数字整除,我们就称它为公平数。例如102是一个公平数(因为它可以被2和8整除),但282不是(因为它不能被8整除)。现在给定一个正整数n,求最小的一个正整数x满足以下条件:

  • x≥n;
  • x是一个公平数。

输入格式

第一行包含一个整数T(1≤T≤1000),表示测试用例组数。
接下来𝑇T行每行都包含一个正整数n(1≤n≤1018)。

输出格式

每个测试用例打印一个整数。

输入样例

4
1
282
1234567890
1000000000000000000

输出样例

1
288
1234568040
1000000000000000000

解题思路:

如果一个正整数能被它每一位上的非零数字整除,那么这个正整数也能被它的每一位上非零数字的LCM整除。而LCM(1...9)=2520,所以符合条件的解一定不超过n+2520。所以我们依次枚举比n大的每一个数并判断是否符合条件即可。

#include <bits/stdc++.h>
using namespace std;
#define int long long
int gcd(int a,int b){return b == 0 ? a : gcd(b,a % b);}
int lcm(int a,int b){return a * b / gcd(a,b);}
bool check(int n)
{
    int x = n;
    while(x)
    {
        int k = x % 10;
        if(k != 0)
        {
            if(n % k != 0)return false;
        }
        x /= 10;
    }
    return true;
}

void solve()
{
    int n;cin >> n;
    while(!check(n))n++;
    cout << n << '\n';
}

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

E:特别的多项式

题目描述

Piper近日又开始研究上了多项式,但是这次𝑃𝑖𝑝𝑒𝑟Piper研究的多项式并非普通的多项式了。

我们知道,一元𝑛n次多项式可以用如下的表达式来表示:

为了有趣一些,Piper规定:一个由不同非负整数组成的数组b,由这个数组b中所有元素得到一个多项式,其中bi​次项的系数为1,将一个正数n代入这个多项式得到的计算结果是特殊数。

换句话说,如果一个正数可以写成 n 的不同非负幂的和,我们就称它为特殊数。例如,对于 n=4 来说,数字 17 是特殊的,因为它可以写成 40+42=1+16=17 ,但 9 不是。

但是Piper懒惰的毛病又犯了,可是他又想快速地找到按递增顺序排列的 k 这个特殊的数字。请你写个程序来帮助Piper。因为这个数可能太大,所以输出它的模数 109+7 。

输入描述

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

每个测试用例的第一行,也是唯一一行,包含两个整数 𝑛n 和 k ( 2≤n≤109 ; 1≤k≤109 )。

输出描述

输入样例

输出样例

解题思路:

 byd这题不会,有没有佬教教

#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const int p = 1e9 + 7;

void solve()
{
    ll n, k; cin >> n >> k;
    ll temp = 1;
    ll ans = 0;
    for(int i = 0; i < 31; ++i)
    {
        if(k & (1 << i))
        {
            ans = (ans + temp) % p;
        }
        temp *= n;
        temp %= p;
    }

    cout << ans << '\n';
}

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

当时AC了三道,第四题后来看懂了,第五题还是不会,等会了再来更新

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值