C++练习2022年蓝桥杯选拔赛

Posted ZSYL

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++练习2022年蓝桥杯选拔赛相关的知识,希望对你有一定的参考价值。

前言

写此篇仅为练习C++,刚好练练手,C++代码来源宋神sqr,研究大佬的C++代码,致谢!

A: 通辽

题目描述

小j到达了火星,发现这里的领土未被开垦,先到先到。他选择了一块面积为x km²的土地,已知通辽的面积约为59535 km²,请问小j选择的这块土地,相当于几个通辽?

输入

第一行输入一个非负整数x,表示小j选择的土地面积。(0 ≤ x ≤ 100000000)	

输出

请输出小j的领土相当于几个通辽,结果四舍五入保留一位小数。

样例输入

59536

样例输出

1.0

题解

  • 简单的浮点数运算。
  • 时间复杂度 O(1)。

C++

#pragma Gcc optimize(3,"inline","Ofast");
#include<bits/stdc++.h>
using namespace std;
#define int long long
typedef long long ll;
 
signed main()
    double d;cin>>d;
    printf("%.1f",d/59535);

C++竟然可以用printf(),这样格式化输出就方便多了吧,前几天还在头疼C++怎么格式化输出结果,网上一搜发现很麻烦。

signed main():有符号的main

【C++疑问】signed main 和 int main 的区别?

Java

import java.util.Scanner;
 
public class Main 
    public static void main(String[] args) 
    
        Scanner sc = new Scanner(System.in);
        
        double n = sc.nextDouble();
         
        System.out.printf("%.1f", n/59535);
    

B: 仿生机器人

题目描述

j正在研究一种仿生机器人,他一共研制了m款机器人,并对它们进行了n次实验得到了一个数据矩阵。经过j一直在进行优化,但是机器人的能力不一定随着轮数的而增强。
j认为一次合理的优化,是所有的机器人能力都有所增加。
在n轮实验后,他准备写一本优化指南,选取n轮优化中的一些轮,并满足每次优化后m个机器人的能力均提升。

输入

第一行输入两个正整数n和m,分别表示优化轮数以及机器人的数目。(1 ≤ n ≤ 20001 ≤ m ≤ 10 )

接下来n行,每行输入m个正整数。其中a[i][j](1 ≤ a[i][j]1000)表示在第i轮实验中机器人j的能力值。

输出

能选取的最多实验轮数。

样例输入

4 3
1 2 3
2 3 4
2 4 5
3 4 5

样例输出

3

提示

选取第124次实验,2对于14对于2都满足每个机器人的能力值递增。

题解

  • 问题简化完就是对于行的上升子序列,设 d[i]表示以第 i 行为结尾的最长上升子序列长度,每次从之前行转移,判断 j 行是否满足每列元素均小于第 i 行的元素,若满足则转移。
  • 时间复杂度 O(𝑛2 ∗ 𝑚)。

C++

#pragma Gcc optimize(3,"inline","Ofast");
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define int ll
 
int a[2010][11];
int n,m;
 
bool check(int i,int j)
    for(int k = 1;k<=m;++k)
        if(a[i][k] <= a[j][k])
            return false;
    return true;

int dp[2010];
 
signed main()
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    cin>>n>>m;
    for(int i = 1;i<=n;++i)
    for(int j = 1;j<=m;++j)
        cin>>a[i][j];
    
    int ans = 0;
    for(int i = 1;i<=n;++i)
        dp[i] = 1;
        for(int j = 1;j < i;++j)
            if(check(i,j))
                dp[i] = max(dp[i],dp[j] + 1);
        
        ans = max(ans,dp[i]);
    
    cout<<ans;

动态规划,第i行每次判断[1-i)的每一行是否小于i行,小于就更新,循环外更新最大结果值。

C: 加减乘除

题目描述

给出你两个分数和操作符号,请你计算出最终的结果,并化简输出。

输入

第一行输入一个T,表示测试组数(1 ≤ T ≤ 100)

接下来T行,每行按照a/b op c/d的格式输入,a,b,c,d均为≤100正整数,op为字符'+', '-', '*', '/'中的一种。

输出

输出T行为每组运算结果e/f,满足最简式。若e/f为整数,则输出e/f的整数结果。如果结果是负数,则将负号放置最前面。

样例输入

5
1/2 + 1/3
1/3 - 1/4
1/2 * 2/1
1/6 / 5/2
1/3 - 1/2

样例输出

5/6
1/12
1
1/15
-1/6

题解

  • 求出分子和分母后,再求其最大公约数化简,本题数字范围不大,使用暴力求约数和辗转相除法都可以。
  • 时间复杂度 O(log2 𝑛)。

C++

#pragma Gcc optimize(3,"inline","Ofast");
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define int ll
signed main()
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    int T;cin>>T;
    while(T-->0)
        int a,b,c,d;char op,c1,c2;  // c1, c2缓冲字符/
        cin>>a>>c1>>b>>op>>c>>c2>>d;
        int s,x,g;
        if(op == '+')
            s  = a * d + c * b;
            x = b * d;
            g  = __gcd(s,x);
        else if(op == '-')
            s  = a * d - c * b;
            x = b * d;
            g  = __gcd(s,x);
        else if(op == '*')
            s = a * c;
            x = b * d;
            g = __gcd(s,x);
        else
            s = a * d;
            x = c * b;
            g = __gcd(s,x);
        
        // 计算符号
        int fh = (s / abs(s)) * (x / abs(x));
        g = abs(g),s = abs(s),x = abs(x);
        // 化简约去最大公约数
        s /= g,x /= g;
        if(s == 0||x == 0)
            cout<<0<<"\\n";
        else
	        if(fh == -1) cout<<"-";
	        if(s % x == 0)
	            cout<<s / x<<"\\n";
         else 
            cout<<abs(s)<<"/"<<abs(x)<<"\\n";
        
        
    

Java

import java.util.Scanner;
 
public class Main 
    public static void main(String[] args) 
        Scanner sc = new Scanner(System.in);
         
        int n = sc.nextInt();
         
        sc.nextLine();
         
        while (n-- > 0) 
            String s[] = sc.nextLine().split(" ");
            int a = Integer.parseInt(s[0].split("/")[0]);
            int b = Integer.parseInt(s[0].split("/")[1]);
            int c = Integer.parseInt(s[2].split("/")[0]);
            int d = Integer.parseInt(s[2].split("/")[1]);
             
            if (s[1].equals("+")) 
                int min = getMin(b, d);
                a = min/b*a;
                c = min/d*c;
                int e = a+c;
                if (e == min)
                    System.out.println(1);
                else if (e % min == 0)
                    System.out.println(e / min);
                else if (min % e == 0)
                    System.out.println(1 + "/" + (min/e));
                else 
                    int max = getMax(e, min);  // 1/6 - 3/6
                    System.out.println(e/max+"/"+min/max);
                
                
             else if (s[1].equals("-")) 
                 
                int min = getMin(b, d);
                a = min/b*a;
                c = min/d*c;
                int e = a-c;
                if (e == 0)
                    System.out.println("0");
                else if (e == min)
                    System.out.println(1);
                else if (-e == min)
                    System.out.println(-1);
                else if (e % min == 0)
                    System.out.println(e / min);
                else 
                    int max = getMax(Math.abs(e), min);  // 1/6 - 3/6
                    System.out.println(e/max+"/"+min/max);
                
                 
             else if (s[1].equals("*")) 
                int i = a * c;
                int j = b * d;
                if (i == j) 
                    System.out.println(1);
                 else if (j % i == 0)
                    System.out.println(1 + "/" + (j/i));
                 else if (i % j == 0) 
                    System.out.println(i/j);
                 else 
                    int max = getMax(i, j);
                    i /= max;
                    j /= max;
                    System.out.println(i + "/" + j);
                
             else 
                int i = a * d;
                int j = b * c;
                if (i == j) 
                    System.out.println(1);
                 else if (j % i == 0)
                    System.out.println(1 + "/" + (j/i));
                 else if (i % j == 0) 
                    System.out.println(i/j);
                 else 
                    int max = getMax(i, j);
                    i /= max;
                    j /= max;
                    System.out.println(i + "/" + j);
                
            
        
    
    public static int getMin(int b, int d) 
        for (int i = 1; i <= b*d; i++) 
            if (i % d == 0 && i % b == 0)
                return i;
        
         
        return b*d;
    
    public static int getMax(int i, int j) 
        if (j == 0) 
            return i;
        
        return getMax(j, i%j);
    

Java代码太复杂繁琐了,还是使用C++的思路更好,直接暴力计算出分子分母,再求出最大公约数化简即可!

D: 雷霹数

题目描述

霹雷一声震天响,雷霹数指把一个数分成两半的数加起来,再平方,正好是原来的数字。
有位外国数学家叫卡普利加,在一次旅行中,遇到猛烈的暴风雨,电闪雷鸣过后,他看到路边一块里程碑,被雷电劈成两半,一半上刻着30,另一半刻着25。这时,卡普利加的脑际中忽然发现了一个绝妙的数学关系——30+25=55 55×55=3025把劈成两半的数加起来,再平方,正好是原来的数字。
本题给出你L和R,请问在L~R内有多少雷霹数。显然你的数字需要能分成两半,例如数字1~9,只有一位,那么不满足分成两半。对于前导0,例如数字3004,你将其分成3004的时候前一部分为30,后一部分为04,则视为4。所以和就是30+4 = 304304×304=92416,不满足雷霹数性质,所以3004不是雷霹数。本题对于分开的位数没有限制,例如3025可以分成30253025以及3025。

输入

输入两个正整数L 和 R(1 ≤ L ≤ R ≤ 1000000)

输出

输出范围内的所有霹雳数,每个数字占一行,如果没有满足条件的数字,则输出"NONE"。

样例输入

2024 3025

样例输出
2025
3025

题解

  • 模拟题,枚举范围内的数字,再枚举当前数字分割的位数判断即可。
  • 时间复杂度 O(𝑛 ∗ 𝑙𝑔 𝑛)。

C++

#pragma Gcc optimize(3,"inline","Ofast");
<

以上是关于C++练习2022年蓝桥杯选拔赛的主要内容,如果未能解决你的问题,请参考以下文章

2022年蓝桥杯第二次校内选拔赛

PTA2022年蓝桥杯及天梯赛赛前训练(C++练习)

2022年11月第十四届蓝桥杯校模拟赛详解+代码

长沙学院2022蓝桥杯选拔赛第一场

考题解析2021年4月蓝桥杯省赛C++中级组

蓝桥杯c++选拔大赛A组与B组啥区别?