2023 HBU 天梯赛第二次测试 题目集

目录

1 考试成绩

2 切割木棒

3 美丽的点对

4 幸运数字

5 增加硬币

6 日落大道

7 ICPC保定站

8 染色问题

9 序列匹配

10 简单的异或

11 选我啊!


1 考试成绩

Rain Sure同学在参加一场面试,一共有n道题目,他的初始分数为m分。

Rain Sure回答错一道题目就会扣一分,但是分数不会小于0;回答正确一道题目就会加一分。

给定一个长度为n的字符串,第i个字符如果为o,代表第i道题目Rain Sure回答正确了;如果第i个字符为x,代表第i道题目Rain Sure同学回答错误。

请你计算他的最终分数是多少。

输入格式

第一行两个整数分别代表nm

第二行一个长度为n的字符串,代表Rain Sure同学的回答情况。

1≤n≤2×105

0≤m≤2×105

保证字符串中只会出现o和x

输出格式

请输出Rain Sure同学的最终分数。

测试样例一

3 0
xox
0

参考代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
int main()
{
    int n,m;
    cin>>n>>m;
    getchar();
    string s;
    cin>>s;
    for(int i=0;i<s.size();i++){
        if(s[i] == 'o')m++;
        if(s[i] == 'x')m--;
        m = max(0,m);
    }
    
    cout<<m;
    return 0;
}

2 切割木棒

黑涩会老大Arbalest给了Rain Sure一个长度为n的木棒,要求他求出将这个木棒切割为12段(每段的长度必须是一个正整数)的方案数。

Rain Sure表示这个问题太简单了,请你帮他求出答案。

输入格式

输入为一个正整数表示n

12≤n≤200

输出格式

请你输出方案数

测试样例一

12
1

测试样例二

13
12

参考代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 210;
LL f[N][13];
int main()
{
    for (int i = 0; i < N; i++) {
        for (int j = 0; j <= i && j < 13; j++) {
            if (j == 0)f[i][j] = (LL)1;
            else f[i][j] = f[i - 1][j - 1] + f[i - 1][j];
        }
    }
    int n; cin >> n;
    cout << f[n - 1][11];
    return 0;
}

3 美丽的点对

Rain Sure同学给了你二维平面上的n个点,编号从1 - n,第i个点的坐标为(xi,yi),并且n个点的坐标互不相同。

Rain Sure想让你求出满足以下条件的点对(i,j)(i<j)的数量:

i和点j构成的直线的斜率需要在[−1,1]之间。

输入格式

第一行一个正整数n

后面n行,每行两个整数(xi,yi),代表第i个点的坐标。

1≤n≤103

xi∣,∣yi∣≤103

xi=xj,i=j

输出格式

请你求出点对的数量。

测试样例一

3
0 0
1 2
2 1
2

参考代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 3000;
pair<int,int> ver[N];
int n;

int main()
{
    int a,b;
    scanf("%d",&n);
    for(int i=0;i<n;i++){
        scanf("%d%d",&a,&b);
        ver[i].first=a,ver[i].second=b;
    }
    int res=0;
    for(int i=0;i<n;i++){
        for(int j=i+1;j<n;j++){
            double k = ((double)ver[j].second-ver[i].second)/((double)ver[j].first-ver[i].first);
            if(k>=(double)-1 &&k<=(double)1)res++;
        }
    }
    cout<<res;
    return 0;
}

4 幸运数字

Rain Sure同学定义了幸运数字——如果一个正整数n是幸运数字,那么当且仅当n和(n+1)/2都是素数。

现在给定q次查询:

i次询问给定两个正整数li,ri,请你求出在区间[li,ri]中有多少个数字是幸运数字。

输入格式

第一行一个正整数q

后面q行,每行两个正整数li,ri

1≤q≤105

1≤liri≤105

输出格式

对于每次询问,输出答案,每个答案单独占据一行。

测试样例一

1
3 7
2

参考代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1e5+10;
int prime[N],cnt;
int s[N];
bool st[N];
void get_prime(int n){
    for(int i=2;i<=n;i++){
        if(!st[i]){
            prime[cnt++]=i;
        }
        for(int j=0;prime[j]<=n/i;j++){
            st[prime[j]*i]=true;
            if(i%prime[j]==0)break;
        }
    }
}

int main()
{
    get_prime(N-1);
    for(int i=2;i<N;i++){
        if(!st[i] && !st[(i+1)/2] && i%2==1)s[i]=1;
    }
    for(int i=2;i<N;i++)s[i]+=s[i-1];
    int q;
    cin>>q;
    while(q--){
        int l,r;
        scanf("%d%d",&l,&r);
        printf("%d\n",s[r]-s[l-1]);
    }
    return 0;
}

5 增加硬币

在一个袋子里装着A枚金币,B枚银币,C枚铜币

你需要将袋子里任意一种硬币变成至少100枚,你可以不断进行如下操作:

从袋子里随机选择一枚硬币,将其拿出袋子,然后将与这枚硬币相同的两枚硬币放入袋子中。

请你求出最少操作次数的期望值。

输入格式

输入一行,包括三个整数,分别代表A,B,C

0≤A,B,C≤99

A+B+C≥1

输出格式

输出最少操作次数的期望值。

当你输出的答案与标准答案的误差不超过10−6时,认为你的答案是正确的。

测试样例一

99 99 99
1.000000000

参考代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 110;
double f[N][N][N];
int d = 0;

double dp(int a, int b, int c) {
    if (f[a][b][c] >= 0)return f[a][b][c];
    f[a][b][c] = 0;
    if (a >= 100 || b >= 100 || c >= 100)return f[a][b][c];
    int sum = a + b + c;
    f[a][b][c] += (dp(a + 1, b, c) + 1) * (1.0 * a) / sum;
    f[a][b][c] += (dp(a, b + 1, c) + 1) * (1.0 * b) / sum;
    f[a][b][c] += (dp(a, b, c + 1) + 1) * (1.0 * c) / sum;
    return f[a][b][c];
}
int main()
{
    int a, b, c;
    scanf("%d%d%d", &a, &b, &c);
    memset(f, -1, sizeof f);
    printf("%.9lf", dp(a, b, c));

    return 0;
}

6 日落大道

给定一个nm列的网格a,其中ai,j一定是这些字符中的一个S, G, ., #, a, ⋯, z。

其中#代表障碍物,你不可以走到这里,a ⋯ z代表不同种类的传送门。

Rain Sure同学一开始位于S处,他想要去G处,每次移动他可以进行下面两种操作中的一种:

  • 移动到上下左右相邻中的一个格子,要求这个格子不能出界,不能是障碍物
  • 进行传送,假如当前所在的位置是一个小写字母,他可以传送到任意一个是同样字母的位置。

请你求出Rain Sure同学从S移动到G所花费的最短时间。

如果不能到达,请输出-1。

输入格式

第一行两个正整数,分别代表nm

下面n行,每行m个字符,代表网格a

1≤n,m≤2000

ai,j一定是S, G, ., #, a, ⋯, z中的一个。

保证只有一个位置是S,只有一个位置是G。

输出格式

请输出Rain Sure同学从S移动到G的最短时间,如果不能到达则输出-1。

测试样例一

2 5
S.b.b
a.a.G
4

7 ICPC保定站

Rain Sure同学来保定参加2077年的ICPC保定站了,这场比赛一共有n道题目,将会持续T分钟。

凭借他的超能力,Rain Sure同学可以预测到他可以花ai分钟来AC掉第i个题目。

所以,他将会从这n道题目中选择一些题目来做,当然也有可能全都做(因为AK最腻害了),但是要保证花费的总时间不超过T分钟。

请你求出他能够在做题上花费的最长时间。

输入格式

第一行包括两个正整数,分别为nT

第二行有n个正整数,分别代表AC这道题需要花费的时间。

1≤n≤40

1≤T≤109

1≤ai≤109

输出格式

请输出Rain Sure同学能在做题上花费的最长时间。

测试样例一

5 17
2 3 5 7 11
17

参考代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 50;
typedef pair<int, int> PII;
int n, t, k;
int w[N];
LL weights[1 << 24], cnt = 0;
LL res;

void dfs1(int u, LL s) {
    if (u == k) {
        weights[cnt++] = s;
        return;
    }

    dfs1(u + 1, s);
    if (s + w[u] <= t)dfs1(u + 1, s + w[u]);
}

void dfs2(int u, LL s) {
    if (u == n) {
        int l = 0, r = cnt - 1;
        while (l < r) {
            int mid = l + r + 1 >> 1;
            if (weights[mid] <= (LL)t - s)l = mid;
            else r = mid - 1;
        }
        if (weights[l] + s <= t)
            res = max(res, weights[l] + s);
        return;
    }

    dfs2(u + 1, s);
    if (w[u] + s <= t)dfs2(u + 1, s + w[u]);
}


int main()
{
    scanf("%d%d", &n, &t);
    for (int i = 0; i < n; i++)scanf("%d", &w[i]);

    sort(w, w + n);
    reverse(w, w + n);

    k = n / 2;

    dfs1(0, 0);

    sort(weights, weights + cnt);
    cnt = unique(weights, weights + cnt) - weights;
    dfs2(k, 0);

    cout << res;
    return 0;
}

8 染色问题

Arbalest给了Rain Suren个小方格。

并且其中有m个小方格的颜色是蓝色的,分别为a1,a2,a3,⋯,am,其余均为白色。

Arbalest让Rain Sure任意选择一个正整数k.

Rain Sure同学之后可以进行如下操作,选定一个长度为k的连续小方格(其中不许出现蓝色),将他们全部染成红色。

Arbalest让Rain Sure把这n个小方格中白色的小方格全部变成红色。

请你帮助Rain Sure同学决定正整数k,并求出最少需要的操作次数。

输入格式

第一行包括两个整数,分别代表nm

第二行m个正整数a1,a2,⋯,am,其中ai代表第i个蓝色小方格的位置。

1≤n≤109

0≤m≤2×105

1≤ain

保证ai各不相同

全部输入均为整数。

输出格式

请你输出最少需要的操作次数

测试样例一

5 2
1 3
3

参考代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2e5+10;
int n,m;
int s[N],w[N],cnt;
int gcd(int a,int b){
    return b?gcd(b,a%b):a;
}
int main()
{
   scanf("%d%d",&n,&m);
    if(m==0){
        cout<<1;
        return 0;
    }
    if(n==m){
        cout<<0;
        return 0;
    }
   for(int i=1;i<=m;i++)scanf("%d",&w[i]);
   sort(w+1,w+m+1);
   w[0]=0;
   for(int i=1;i<=m;i++){
    int d = w[i]-w[i-1]-1;
    if(d>0)s[cnt++]=d;
   }
   int d = n-w[m];
   if(d>0)s[cnt++]=d;
   
   sort(s,s+cnt);
   int lst=s[0];
   int res=1;
   for(int i=1;i<cnt;i++){
    if(s[i]%lst==0)res+=s[i]/lst;
    else res+=s[i]/lst+1;
   }
   cout<<res;
   
    return 0;
}

9 序列匹配

给定一个长度为n的序列A和一个长度为为m的序列B

Rain Sure同学从序列A中删除一些元素得到一个新的序列A

同理,也从序列B中删除一些元素得到一个新的序列B′.

并且,保证∣A′∣=∣B′∣,也就是两个新的序列长度相等。

x代表序列A和序列B中一共删除的元素的数量,y表示Ai′=Bi′(1≤i≤∣A′∣)

请你输出x+y最小可能的值。

输入格式

第一行两个正整数,分别代表nm

第二行n个正整数,代表序列A.

第三行m个正整数,代表序列B.

1≤n,m≤1000

1≤Ai,Bi≤109

输出格式

请你输出x+y最小可能的值。

测试样例一

4 3
1 2 1 3
1 3 1
2

参考代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1010;
typedef pair<int, int> PII;
int n, m;
int a[N], b[N];
int f[N][N];

int main()
{
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; i++)scanf("%d", &a[i]);
    for (int i = 1; i <= m; i++)scanf("%d", &b[i]);
    memset(f, 0x3f, sizeof f);
    for(int i=0;i<=n;i++)f[i][0]=i;
    for(int j=1;j<=m;j++)f[0][j]=j;
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            f[i][j] = min(f[i - 1][j] + 1, f[i][j - 1] + 1);
            if (a[i] == b[j]) f[i][j] = min(f[i][j], f[i - 1][j - 1]);
            else f[i][j] = min(f[i][j], f[i - 1][j - 1] + 1);
        }
    }
    cout << f[n][m];
    return 0;
}

10 简单的异或

为了考察大家对于数据结构的学习,Rain Sure同学想了一道比较简单而又经典的题目。

给定一个长度为n的序列A.

将进行q次查询,每次查询为下面两种中的一个:

1 x y: 令Ax=Axy

2 x y:输出AxAx+1⊕Ax+1⊕⋯⊕Ay

ab代表ab的异或

输入格式

第一行两个正整数,分别代表nq

第二行n个整数,代表序列A

1≤n≤300000

1≤q≤300000

0≤Ai<230

对于操作1,保证1≤xn,0≤y<230

对于操作2,保证1≤xyn

输出格式

对于每个操作2,请输出答案。

测试样例一

3 4
1 2 3
2 1 3
2 2 3
1 2 3
2 2 3
0
1
2

参考代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int N = 300010;

int n, m;
int a[N], tr[N];

int lowbit(int x)
{
    return x & -x;
}

void add(int x, int v)
{
    for (int i = x; i <= n; i += lowbit(i)) tr[i] ^= v;
}

int query(int x)
{
    int res = 0;
    for (int i = x; i; i -= lowbit(i)) res ^= tr[i];
    return res;
}

int main()
{
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
    for (int i = 1; i <= n; i++) add(i, a[i]);

    while (m--)
    {
        int k, x, y;
        scanf("%d%d%d", &k, &x, &y);
        if (k == 2) printf("%d\n", query(y) ^ query(x - 1));
        else add(x, y);
    }

    return 0;
}

11 选我啊!

HBU最近在进行花美男的选举,候选人是A同学和B同学。

HBU一共有n个学院,其中第i个学院有ai名同学支持A同学,bi名同学支持B同学。

但是,B同学可以在每个学院发表演讲来获得更多的同学对他的支持。

如果B同学在某个学院进行了一场演讲,那么这个学院的全部同学都会支持他,包括原来支持A同学的那些同学。

相反,如果B同学不在某个学院发表演讲,那么这个学院中原来支持A同学的那些同学还会支持A同学,但是那些原来支持B同学的同学们将不再支持B同学,他们会变的中立——谁也不支持。

请你求出B同学最少在几个学院发表演讲才能让支持他的同学人数超过支持A同学的人数。

输入格式

第一行一个正整数n

后面n行,每行两个正整数(ai,bi),分别代表第i个学院中支持A同学的人数和支持B同学的人数。

1≤n≤2×105

1 ≤ai,bi≤109

输出格式

请输出答案

测试样例一

4
2 1
2 2
5 1
1 3
1

参考代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2e5 + 10;
struct stu {
    LL a, b, c;
}st[N];

LL resa;
int n;
bool cmp(stu s1, stu s2) {
    return s1.c > s2.c;
}
int main()
{
    scanf("%d", &n);
    for (int i = 0; i < n; i++) {
        scanf("%d%d", &st[i].a, &st[i].b);
        resa += st[i].a;
        st[i].c = st[i].a * 2 + st[i].b;
    }
    sort(st, st + n, cmp);
    int res = 0;
    for (int i = 0; i < n; i++) {
        if (resa < 0)break;
        resa -= st[i].c;
        res++;
    }
    cout << res;

    return 0;
}

参考代码:

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

星河边采花

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

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

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

打赏作者

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

抵扣说明:

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

余额充值