蓝桥杯2022(B组)

本文介绍了作者作为大一学生初次参加ACM比赛的经历,拿到省三等奖并分享了错失省二等奖的遗憾。文章列举了几个编程题目,包括进制转换、顺子日期统计、刷题计划计算、灌木修剪高度预测、进制减法和子矩阵元素和统计等,并提供了相应的解题思路和代码示例。这些题目涵盖了算法和逻辑思维的多个方面。
摘要由CSDN通过智能技术生成

@[TOC]

分析:

本人今年大一刚接触acm拿了个省三,本来能省二的题目交错,啊啊啊啊啊到了最后一份中才发现改都改不了了错失省二明年加油,但我同学有的省一膜拜膜拜;

@[top]

# 填空题

##1 进制转换

问题描述】
九进制正整数 

​    
  9进制转换成十进制等于多少?

【答案提交】
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。

题解
经典进制转换

print(2 + 2 * 9 + 0 * 9 * 9 + 2 * 9 * 9 * 9)

答案 1478


# B 顺子日期 (5分)

【问题描述】
小明特别喜欢顺子。顺子指的就是连续的三个数字:123 123123、456 456456 等。顺子日期指的就是在日期的 y y y y m m d d yyyymmddyyyymmdd 表示法中,存在任意连续的三位数是一个顺子的日期。例如 20220123 2022012320220123 就是一个顺子日期,因为它出现了一个顺子:123 123123;而 20221023 2022102320221023 则不是一个顺子日期,它一个顺子也没有。小明想知道在整个 2022 20222022 年份中,一共有多少个顺子日期。

【答案提交】
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
分析:

012算是顺子日期但是210不算

答案 4/14(不知道是哪个但好像14更对);

C 刷题统计 (10分)


【问题描述】
小明决定从下周一开始努力刷题准备蓝桥杯竞赛。他计划周一至周五每天做 a aa 道题目,周六和周日每天做 b bb 道题目。请你帮小明计算,按照计划他将在第几天实现做题数大于等于 n nn 题?

【输入格式】
输入一行包含三个整数 a aa, b bb 和 n nn.

【输出格式】
输出一个整数代表天数。

【样例输入】

10 20 99
1
【样例输出】

8
1
【评测用例规模与约定】
对于 50 % 50\%50% 的评测用例,1 ≤ a , b , n ≤ 1 0 6 1 ≤ a, b, n ≤ 10^61≤a,b,n≤10 
6
 .
对于 100 % 100\%100% 的评测用例,1 ≤ a , b , n ≤ 1 0 18 1 ≤ a, b, n ≤ 10^{18}1≤a,b,n≤10 
18

 思路:n的数据范为非常大,不能通过遍历每一个数将其相加来计算,所以我们应该算出一周的总刷题量,用总刷体谅/每一周的刷题量计算出要几周,取余的数一天一天遍历即可;

#include<bits/stdc++.h>
using namespace std;
long long int a,b,c,s,n,m;
int main(){
    cin>>a>>b>>c;
n=5*a+2*b;
m=c%n;s=c/n*7;
int i=0;
while(m>0){
    ++i;
    if(i>5){
        m=m-b;
    }
    else m=m-a;
    s++;
}
printf("%lld",s);
}

D 修剪灌木 (10分)

【问题描述】
爱丽丝要完成一项修剪灌木的工作。
有 N NN 棵灌木整齐的从左到右排成一排。爱丽丝在每天傍晚会修剪一棵灌木,让灌木的高度变为 0 00 厘米。爱丽丝修剪灌木的顺序是从最左侧的灌木开始,每天向右修剪一棵灌木。当修剪了最右侧的灌木后,她会调转方向,下一天开始向左修剪灌木。直到修剪了最左的灌木后再次调转方向。然后如此循环往复。
灌木每天从早上到傍晚会长高 1 11 厘米,而其余时间不会长高。在第一天的早晨,所有灌木的高度都是 0 00 厘米。爱丽丝想知道每棵灌木最高长到多高。

【输入格式】
一个正整数 N NN,含义如题面所述。

【输出格式】
输出 N NN 行,每行一个整数,第 i ii 行表示从左到右第 i ii 棵树最高能长到多高。

【样例输入】

3
1
【样例输出】

4
2
4
1
2
3
【评测用例规模与约定】
对于 30 % 30\%30% 的数据,N ≤ 10 N ≤ 10N≤10.
对于 100 % 100\%100% 的数据,1 < N ≤ 10000 1 < N ≤ 100001<N≤10000.

 思路:

通过计算案例的组成发现该题是有规律的,规律就是max(i-1,n-i)的值;

#include<bits/stdc++.h>
using namespace std;
const int r=100010;
int n,s;
int main(){
    cin>>n;
    for(int i=1;i<=n;i++){
        int c=max(i-1,n-i)*2;
        printf("%d\n",c);
    }
}

E X 进制减法 (15分)

【问题描述】
进制规定了数字在数位上逢几进一。
X XX 进制是一种很神奇的进制,因为其每一数位的进制并不固定!例如说某种 X XX 进制数,最低数位为二进制,第二数位为十进制,第三数位为八进制,则 X XX 进制数 321 321321 转换为十进制数为 65 6565。
现在有两个 X XX 进制表示的整数 A AA 和 B BB,但是其具体每一数位的进制还不确定,只知道 A AA 和 B BB 是同一进制规则,且每一数位最高为 N NN 进制,最低为二进制。请你算出 A − B A − BA−B 的结果最小可能是多少。
请注意,你需要保证 A AA 和 B BB 在 X XX 进制下都是合法的,即每一数位上的数字要小于其进制。

【输入格式】
第一行一个正整数 N NN,含义如题面所述。
第二行一个正整数 M a M_aM 
a
​    
 ,表示 X XX 进制数 A AA 的位数。
第三行 M a M_aM 
a
​    
  个用空格分开的整数,表示 X XX 进制数 A AA 按从高位到低位顺序各个数位上的数字在十进制下的表示。
第四行一个正整数 M b M_bM 
b
​    
 ,表示 X XX 进制数 B BB 的位数。
第五行 M b M_bM 
b
​    
  个用空格分开的整数,表示 X XX 进制数 B BB 按从高位到低位顺序各个数位上的数字在十进制下的表示。
请注意,输入中的所有数字都是十进制的。

【输出格式】
输出一行一个整数,表示 X XX 进制数 A − B A − BA−B 的结果的最小可能值转换为十进制后再模 1000000007 10000000071000000007 的结果。

【样例输入】

11
3
10 4 0
3
1 2 0
1
2
3
4
5
【样例输出】

94
1
【样例说明】
当进制为:最低位 2  进制,第二数位 5  进制,第三数位 11  进制时,减法得到的差最小。此时 A 在十进制下是 108 ,B 在十进制下是 14 ,差值是 94 

题解
X XX 进制数 321 321321 是如何转换为十进制数 65 6565 的:
最低数位为二进制,十进制为 1 ∗ 1 1 * 11∗1;
第二数位为十进制,十进制为 2 ∗ 2 2 * 22∗2;
第三数位为八进制,十进制为 3 ∗ 2 ∗ 10 3 * 2 * 103∗2∗10;
加起来即为 65 6565 。

每一位的进制要尽可能小。
进制最小的时候所取得差值最小;

 

#include<bits/stdc++.h>
using namespace std;
const int r=1000010;
const int w=1000000007;
int a[r],b[r];long long int n,n1,m1,m,s,res,p[r],aa[r],bb[r],s1,s2; long long int mul[r];
int main(){
    cin>>n;
    cin>>n1;
for(int i=n1;i>=1;i--){
        cin>>a[i];
}
    cin>>m1;
    for(int i=m1;i>=1;i--)
        cin>>b[i];
      
    
    for(int i=n1;i>=1;i--){
        p[i]=max(a[i],b[i])+1;
        if(p[i]<2)p[i]=2;
    }mul[1]=1;
 for(int i=2;i<=n1;i++){
     mul[i]=p[i-1]*mul[i-1]%w;
 }
 for(int i=n1;i>=1;i--){
    s1=(s1+a[i]*mul[i])%w;
 }
 for(int i=m1;i>=1;i--){
     s2=(s2+b[i]*mul[i])%w;
 }
 printf("%d",(s1-s2+w)%w);
}

 F 统计子矩阵 (15分)

【问题描述】
给定一个 N × M N × MN×M 的矩阵 A AA,请你统计有多少个子矩阵(最小 1 × 1 1 × 1,最大 N × M N × M) 满足子矩阵中所有数的和不超过给定的整数 K ?

【输入格式】
第一行包含三个整数 N , M 和 K .
之后 N 行每行包含 M  个整数,代表矩阵 A 

【输出格式】
一个整数代表答案。

【样例输入】

3 4 10
1 2 3 4
5 6 7 8
9 10 11 12
1
2
3
4
【样例输出】

19
1
【样例说明】
满足条件的子矩阵一共有 19 1919,包含:
大小为 1 × 1 的有 10 1个。
大小为 1 × 2 的有 3  个。
大小为 1 × 3的有 2 个。
大小为 1 ×  1 × 4的有 1  个。
大小为 2 × 1  的有 3 个。

 该题思路:

使用前缀和进行计算出来值,计算出每一个区间的前缀和判断是否满足题目条件;

只能得70%的分

#include <bits/stdc++.h>
#define ll long long
#define N 502
using namespace std;
int n, m, k;
int a[N][N], sum[N][N];
ll ans = 0;
int main() {
    scanf("%d%d%d", &n, &m, &k);
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= m; ++j) {
            scanf("%d", &a[i][j]);
        }
    }
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= m; ++j) {
            sum[i][j] =
                a[i][j] + sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1];
        }
    }
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= m; ++j) {
            for (int x = i; x <= n; ++x) {
                for (int y = j; y <= m; ++y) {
                    if (sum[x][y] - sum[x][j - 1] - sum[i - 1][y] +
                            sum[i - 1][j - 1] <=
                        k) {
                        ++ans;
                    }
                }
            }
        }
    }
    printf("%lld\n", ans);
    return 0;
}

G 积木画 (20分)

【问题描述】
小明最近迷上了积木画,有这么两种类型的积木,分别为 I 型(大小为 2
个单位面积)和 L 型(大小为 3 个单位面积):
同时,小明有一块面积大小为 2 × N 的画布,画布由 2 × N 个 1 × 1 区域构
成。小明需要用以上两种积木将画布拼满,他想知道总共有多少种不同的方式?
积木可以任意旋转,且画布的方向固定。
【输入格式】
输入一个整数 N,表示画布大小。
【输出格式】
输出一个整数表示答案。由于答案可能很大,所以输出其对 1000000007 取
模后的值
【样例输入】
3
【样例输出】
5

思路: dp状态压缩现在还不太会复制一个学长代码

#include<bits/stdc++.h>
#define N 10000007
using namespace std;
int n;
const int mod = 1000000007;
int dp[N][4];
int main() {
    scanf("%d", &n);
    dp[1][0] = dp[1][3] = 1;
    for(int i = 2; i <= n; ++i) {
        dp[i][0] = dp[i-1][3];
        dp[i][1] = (dp[i-1][2] + dp[i-1][0]) % mod;
        dp[i][2] = (dp[i-1][1] + dp[i-1][0]) % mod;
        dp[i][3] = ((dp[i-1][0] + dp[i-1][1]) % mod + (dp[i-1][2] + dp[i-1][3]) % mod) % mod;
    }
    printf("%d\n", dp[n][3]);
    return 0;
}

H 扫雷 (20分)

 

【问题描述】
小明最近迷上了一款名为《扫雷》的游戏。其中有一个关卡的任务如下,在一个二维平面上放置着 n nn 个炸雷,第 i ii 个炸雷 ( x i , y i , r i ) (x_i, y_i, r_i)(x 

  的一个圆。
为了顺利通过这片土地,需要玩家进行排雷。玩家可以发射 m mm 个排雷火箭,小明已经规划好了每个排雷火箭的发射方向,第 j jj 个排雷火箭 ( x j , y j , r j ) (x_j, y_j, r_j)(x 

  的一个圆,在其爆炸范围内的炸雷会被引爆。同时,当炸雷被引爆时,在其爆炸范围内的炸雷也会被引爆。现在小明想知道他这次共引爆了几颗炸雷?
你可以把炸雷和排雷火箭都视为平面上的一个点。一个点处可以存在多个炸雷和排雷火箭。当炸雷位于爆炸范围的边界上时也会被引爆。

【输入格式】
输入的第一行包含两个整数 n nn、m mm

【输出格式】
输出一个整数表示答案。

【样例输入】

2 1
2 2 4
4 4 2
0 0 5
1
2
3
4
【样例输出】

2
1
【样例说明】

只会暴力bfs骗粉


#include<iostream>
#include<cmath> 
using namespace std;
int n, m;
int grid[5000][5000];
struct node {
    int x, y, r;
    node() {
    }
    node(int _x, int _y, int _r) {
        x = _x;
        y = _y;
        r = _r;
    }
}no[50001];
void input() {
    cin >> n >> m;
    for (int i = 1; i <= n; i++) {
        cin >> no[i].x >> no[i].y >> no[i].r;
    }
    for (int i = n+1; i <= n+m; i++) {
        cin >> no[i].x >> no[i].y >> no[i].r;
    }
}
double dis(int i, int j) {
    return sqrt((no[i].x - no[j].x) * (no[i].x - no[j].x) + (no[i].y - no[j].y) * (no[i].y - no[j].y));
}
int cnt = 0;
void dfs(int n) {
 
    for (int i = 1; i <= n + m; i++) {
        if (grid[n][i] == 1 && n != i) {
            grid[n][i] =grid[i][n]=0;
            cnt++;
            dfs(i);
        }
    }
}
int main() {
    input();
    for (int i = 1; i <= n+m; i++) {
        for (int j = 1; j <= n+m; j++) {
            if (dis(i, j)<=no[i].r) {
        
                grid[i][j]=1;
            }
        }
    }
    for (int i = n + 1; i <= n + m; i++) {
        dfs(i);
    }
    cout << cnt;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值