C++练习2022年蓝桥杯选拔赛
Posted ZSYL
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++练习2022年蓝桥杯选拔赛相关的知识,希望对你有一定的参考价值。
【C++练习】蓝桥杯选拔赛
前言
写此篇仅为练习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 ≤ 2000,1 ≤ 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
提示
选取第1、2、4次实验,2对于1,4对于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,你将其分成30和04的时候前一部分为30,后一部分为04,则视为4。所以和就是30+4 = 304,304×304=92416,不满足雷霹数性质,所以3004不是雷霹数。本题对于分开的位数没有限制,例如3025可以分成3和025、30和25以及302和5。
输入
输入两个正整数L 和 R(1 ≤ L ≤ R ≤ 1000000)
输出
输出范围内的所有霹雳数,每个数字占一行,如果没有满足条件的数字,则输出"NONE"。
样例输入
2024 3025
样例输出
2025
3025
题解
- 模拟题,枚举范围内的数字,再枚举当前数字分割的位数判断即可。
- 时间复杂度 O(𝑛 ∗ 𝑙𝑔 𝑛)。
C++
#pragma Gcc optimize(3,"inline","Ofast");
<以上是关于C++练习2022年蓝桥杯选拔赛的主要内容,如果未能解决你的问题,请参考以下文章