蓝桥杯练习

发现了一个刷题的好网站,嘿嘿嘿。

ACMORE

题目分类而且全部免费,希望可以一直存在下去,嘿嘿嘿。本文中题目来源于此。

入门训练

A+B问题

题目描述

输入A、B,输出A+B。其中-10000 <= A, B <= 10000。

输入解释

输入的第一行包括两个整数,由空格分隔,分别表示A、B。 说明:“输入格式”是描述在测试你的程序时,所给的输入一定满足的格式。

做题时你应该假设所给的输入是一定满足输入格式的要求的,所以你不需要对输入的格式进行检查。多余的格式检查可能会适得其反,使用你的程序错误。

在测试的时候,系统会自动将输入数据输入到你的程序中,你不能给任何提示。比如,你在输入的时候提示“请输入A、B”之类的话是不需要的,这些多余的输出会使得你的程序被判定为错误。

输出解释

输出一行,包括一个整数,表示A+B的值。 说明:“输出格式”是要求你的程序在输出结果的时候必须满足的格式。

输入样例

1
12 45

输出样例

1
57

思路

因为数据范围很小,int类型足够,如果数据范围变大,则需要考虑longlong long等。

代码

1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>

using namespace std;

int main(){
// Todo
int A, B;
cin >> A >> B;
cout << A + B << endl;

return 0;
}

Fibonacci数列

题目描述

Fibonacci数列的递推公式为:Fn=Fn-1+Fn-2,其中F1=F2=1。

当n比较大时,Fn也非常大,现在我们想知道,Fn除以10007的余数是多少。

输入解释

输入包含一个整数n。

输出解释

输出一行,包含一个整数,表示Fn除以10007的余数。

输入样例

1
10

输出样例

1
55

提示

数据规模与约定 1 <= n <= 1,000,000。

思路

可以看到本题中n的值有可能会变得很大,所以普通的int型肯定不够用了,long估计也够呛,对于很大的数可以先试一下long long类型,如果不行的话,就需要采用“大数运算法”即用数组保存每一数。

Fibonacci数列可以采用递归与非递归解法,本题我先用了递归的解法,但是超时了,因为递归所花的时间太长,故后来又采用了非递归循环的方法。代码都放上去仅供参考。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// 递归方法
// 应该是对的,之前代码删掉了,应该就是这么写的
#include <iostream>

using namespace std;

long f(long n)
{
if (n == 1 || n == 2)
{
return 1;
}
else
{
return f(n-1) + f(n-2);
}
}

int main()
{
// Todo
long n;
cin >> n;
cout << f(n) % 10007 << endl;

return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// 非递归循环
#include <iostream>

using namespace std;

long f(long n)
{
long re = 1;
long t1 = 1;
long t2 = 1;
if ( n == 1 || n == 2)
{
return re;
}
else
{
for (long i = 2; i < n; i++)
{
re = (t1 + t2) % 10007;
t1 = t2;
t2 = re;
}
return re;
}
}

int main()
{
// Todo
long n;
cin >> n;
cout << f(n) << endl;

return 0;
}

注:

非递归方法中有个需要注意的地方就是我最初的代码是现计算f(n)的值再去求余,但是有几个测试用例是错的。估计可能是因为数据过大,导致数据出错,百思不得其解,网上搜了一下,发现很多解法都是先求余,这样的好处就是防止数据过大,我采用这个方法之后,测试全部通过,所以在做这种题目的时候一定需要注意数据的范围

序列求和

题目描述

求1+2+3+...+n的值。

输入解释

输入包括一个整数n。

输出解释

输出一行,包括一个整数,表示1+2+3+...+n的值。

输入样例

1
2
3
4
5
第一组:
4

第二组:
100

输出样例

1
2
3
4
5
第一组:
10

第二组:
5050

提示

数据规模与约定
1 <= n <= 1,000,000,000。

思路

本题的数据范围同样很大,依然采用上方策略,验证long long可行。当全部都是正数时,unsigned long long也是可以的,正数范围可以说是又扩大了一倍。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>

using namespace std;

int main(){
// Todo
long long n;
cin >> n;
long sum = 0;
for (long i = 1; i <= n; i++)
{
sum += i;
}
cout << sum << endl;

return 0;
}

圆的面积

题目描述

给定圆的半径r,求圆的面积。

输入解释

输入包含一个整数r,表示圆的半径。

输出解释

输出一行,包含一个实数,四舍五入保留小数点后7位,表示圆的面积。

输入样例

1
4

输出样例

1
50.2654825

提示

数据规模与约定 1 <= r <= 10000。

思路

  1. 手写代码进行进制转换。
  2. 利用C++自带的格式控制进行操作,大道至简。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
#include <math.h>
#include <iomanip>

using namespace std;


int main(){
// Todo
int r;
cin >> r;
cout << setprecision(7) << fixed << M_PI * r * r << endl;

return 0;
}

注:

本程序中用到PI,使用的时C++库里面的M_PI#define M_PI 3.14159265358979323846 // pi,我自己记的位数不够......

本程序中还用带格式化输出。关于格式化输出如下:

使用流操作算子

C++ 中常用的输出流操纵算子如表 1 所示,它们都是在头文件 iomanip 中定义的;要使用这些流操纵算子,必须包含该头文件。

注意:“流操纵算子”一栏中的星号*不是算子的一部分,星号表示在没有使用任何算子的情况下,就等效于使用了该算子。例如,在默认情况下,整数是用十进制形式输出的,等效于使用了 dec 算子。

流操纵算子 作 用
*dec 以十进制形式输出整数 *
hex 以十六进制形式输出整数 *
oct 以八进制形式输出整数 *
fixed 以普通小数形式输出浮点数 *
scientific 以科学计数法形式输出浮点数 *
left 左对齐,即在宽度不足时将填充字符添加到右边 *
*right 右对齐,即在宽度不足时将填充字符添加到左边 *
setbase(b) 设置输出整数时的进制,b=8、10 或 16 *
setw(w) 指定输出宽度为 w 个字符,或输人字符串时读入 w 个字符 *
setfill(c) 在指定输出宽度的情况下,输出的宽度不足时用字符 c 填充(默认情况是用空格填充) *
setprecision(n) 设置输出浮点数的精度为 n。 在使用非 fixed 且非 scientific 方式输出的情况下,n 即为有效数字最多的位数,如果有效数字位数超过 n,则小数部分四舍五人,或自动变为科学计 数法输出并保留一共 n 位有效数字。 在使用 fixed 方式和 scientific 方式输出的情况下,n 是小数点后面应保留的位数。 *
setiosflags(flag) 将某个输出格式标志置为 1 *
resetiosflags(flag) 将某个输出格式标志置为 0 *
boolapha 把 true 和 false 输出为字符串
*noboolalpha 把 true 和 false 输出为 0、1
showbase 输出表示数值的进制的前缀
*noshowbase 不输出表示数值的进制.的前缀
showpoint 总是输出小数点
*noshowpoint 只有当小数部分存在时才显示小数点
showpos 在非负数值中显示 +
*noshowpos 在非负数值中不显示 +
*skipws 输入时跳过空白字符
noskipws 输入时不跳过空白字符
uppercase 十六进制数中使用 A~E。若输出前缀,则前缀输出 0X,科学计数法中输出 E
*nouppercase 十六进制数中使用 a~e。若输出前缀,则前缀输出 0x,科学计数法中输出 e。
internal 数值的符号(正负号)在指定宽度内左对齐,数值右对 齐,中间由填充字符填充。

表格来源:C语言中文网 C++ cout格式化输出(输出格式)完全攻略

基础练习

十进制转十六进制

题目描述

​ 十六进制数是在程序设计时经常要使用到的一种整数的表示方式。它有0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F共16个符号,分别表示十进制数的0至15。十六进制的计数方法是满16进1,所以十进制数16在十六进制中是10,而十进制的17在十六进制中是11,以此类推,十进制的30在十六进制中是1E。 ​给出一个非负整数,将它表示成十六进制的形式。

输入解释

输入包含一个非负整数a,表示要转换的数。0<=a<=21474836470<=a<=2147483647

输出解释

输出这个整数的1616进制表示

输入样例

1
30

输出样例

1
1E

思路

我当时做的时候就是很简单粗暴,也没多想,就直接用代码实现进制转换,存到字符串中,最后再将字符串反转就好了。代码如下:

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#include <iostream>
#include <algorithm>

using namespace std;

char Re(long long t)
{
switch (t)
{
case 10:
return 'A';
break;
case 11:
return 'B';
break;
case 12:
return 'C';
break;
case 13:
return 'D';
break;
case 14:
return 'E';
break;
case 15:
return 'F';
break;
default:
return char(t + 48);
}
}

string Convert(long long a)
{
string re;

while (a)
{
re += Re(a % 16);
a = a / 16;
}

reverse(re.begin(), re.end());
return re;
}

int main(){
// Todo
long long a;
cin >> a;
cout << Convert(a) << endl;

return 0;
}

这个代码我个人感觉没啥问题的,测试用例大部分都可以跑的通,但是有一个测试用例跑不通我也很纳闷,而且也不知道是哪一个......读者要是发现了可以给我留言。

当然,网上也有很简洁的代码,代码书写的最终目的之一就是大道至简嘛。

1
2
3
4
5
6
7
8
#include <cstdio>
int main()
{
int n;
scanf("%d", &n);
printf("%X", n);
return 0;
}

其实我个人是感觉int类型是有点小的,但是也是可以跑通的,就说明测试用例并没有那么大,如果跑不通了可以切换long等类型。

字串问题

字串问题在别的文章中做过,这里就不多写啦,可以翻一下之前的博客。

字母图形

题目描述

利用字母可以组成一些美丽的图形,下面给出了一个例子:

ABCDEFG

BABCDEF

CBABCDE

DCBABCD

EDCBABC

这是一个5行7列的图形,请找出这个图形的规律,并输出一个n行m列的图形。

输入解释

输入一行,包含两个整数n和m,分别表示你要输出的图形的行数的列数。

输出解释

输出n行,每个m个字符,为你的图形。

输入样例

1
5 7

输出样例

1
2
3
4
5
ABCDEFG
BABCDEF
CBABCDE
DCBABCD
EDCBABC

提示

数据规模与约定 1 <= n, m <= 26。

2021.3.23更。

思路

昨天看书的时候看到双指针,但是又不太一样,但总的来说,其实每次输出本来正序输出的位置都会往后移动一个,把该点记为分界点,在此之前需要逆序输出,在此之后正序输出。逆序的时候,像我这边定义的s字符串逆序输出的位置就是分界点的位置即start。需要注意的是,如果测试用例是输出20行5列的时候,正序输出完之后,逆序还是一直输出的,我之前理解的是,正序输出完了,接下来都是逆序的部分都是一样的,这个想法是错误的,题目的要求是接着往下走。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <iostream>

using namespace std;

int main()
{
char s[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
int n, m, start = 0; // n——行,m——列
cin >> n >> m;

// j表示输出行
for (int j = 0; j < n; j++)
{
// 逆序输出。i表示输出列,条件除了i > 0,第二个条件是控制输出的个数不会超过m
for (int i = start; i > 0 && ((start - i) < m); i--)
{
cout << s[i];
}
// 正序输出
for (int i = start; i < m; i++)
{
cout << s[i - start];
}
start++;
cout << endl;
}

return 0;
}

闰年判断

题目描述

给定一个年份,判断这一年是不是闰年。

当以下情况之一满足时,这一年是闰年:

  1. 年份是4的倍数而不是100的倍数;

  2. 年份是400的倍数。

其他的年份都不是闰年。

输入解释

输入包含一个整数y,表示当前的年份。

输出解释

输出一行,如果给定的年份是闰年,则输出yes,否则输出no。

输入样例

1
2013

输出样例

1
no

提示

数据规模与约定 1990 <= y <= 2050。

思路

这题的话很简单,数据范围1990-2050属于正常的int型。直接根据判断依据,一个if语句即可。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>

using namespace std;

int main()
{
int year;
cin >> year;
if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
{
cout << "yes" << endl;
}
else
{
cout << "no" << endl;
}

return 0;
}

数列特征

题目描述

给出n个数,找出这n个数的最大值,最小值,和。

输入解释

第一行为整数n,表示数的个数。

第二行有n个数,为给定的n个数,每个数的绝对值都小于10000。

输出解释

输出三行,每行一个整数。第一行表示这些数中的最大值,第二行表示这些数中的最小值,第三行表示这些数的和。

输入样例

1
2
5
1 3 -2 4 5

输出样例

1
2
3
5
-2
11

提示

数据规模与约定 1 <= n <= 10000。

思路

这个题目其实很简单,但需要注意的地方就是运行可能会超时,保险起见只用了一个循环进行全部操作。代码如下:

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <iostream>
#include <math.h>

using namespace std;

int main()
{
int len;
cin >> len;
long long *num = new long long[len];
long long sum = 0, min = INT16_MAX, max = INT16_MIN;
for (int i = 0; i < len; i++)
{
cin >> num[i];
sum += num[i];
if (num[i] >= max)
{
max = num[i];
}
if (num[i] <= min)
{
min = num[i];
}
}
cout << max << endl << min << endl << sum << endl;

return 0;
}

查找整数

题目描述

给出一个包含n个整数的数列,问整数a在数列中的第一次出现是第几个。

输入解释

第一行包含一个整数n。

第二行包含n个非负整数,为给定的数列,数列中的每个数都不大于10000。

第三行包含一个整数a,为待查找的数。

输出解释

如果a在数列中出现了,输出它第一次出现的位置(位置从1开始编号),否则输出-1。

输入样例

1
2
3
6
1 9 4 8 3 9
9

输出样例

1
2

提示

数据规模与约定 1 <= n <= 1000。

思路

看一篇题目,首先数据没坑,int够用了。查找算法有很多的,这里我是直接遍历整个输入的数据,找到了就返回下标然后结束程序,没找到就返回-1,运行的也是可以的。直接上代码。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <iostream>

using namespace std;

int main()
{
int len;
cin >> len;
int *num = new int[len];
for (int i = 0; i < len; i++)
{
cin >> num[i];
}

int find;
cin >> find;
for (int i = 0; i < len; i++)
{
if (num[i] == find)
{
cout << i + 1 << endl;
return 0;
}
}
cout << -1 << endl;

return 0;
}

2021.3.24更新

PS:祝我自己生日快乐hhhhhhh,21周岁了,接下来要更加努力呀!

回文数

题目描述

1221是一个非常特殊的数,它从左边读和从右边读是一样的,编程求所有这样的四位十进制数。

输出解释

按从小到大的顺序输出满足条件的四位十进制数。

输出样例

1
1221

思路

只要求四位十进制数,int类型足够,从1000遍历到9999,只要满足回文数的定义就输出,测试回文数可以提取每位数字,然后再加到一起即可。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>

using namespace std;

int main()
{
for (int i = 1000; i < 10000; i++)
{
int q = i / 1000;
int b = i / 100 % 10;
int s = i / 10 % 10;
int g = i % 10;
if (g * 1000 + s * 100 + b * 10 + q == i)
{
cout << i << endl;
}
}

return 0;
}

特殊回文数

题目描述

123321是一个非常特殊的数,它从左边读和从右边读是一样的。 输入一个正整数n, 编程求所有这样的五位和六位十进制数,满足各位数字之和等于n 。

输入解释

输入一行,包含一个正整数n。

输出解释

按从小到大的顺序输出满足条件的整数,每个整数占一行。

输入样例

1
52

输出样例

1
2
3
899998
989989
998899

提示

数据规模和约定 1<=n<=54。

思路

可以接着利用上面的代码,不过需要分别讨论五位数与六位数的情况。这里的话换了一个方法,就是回文数相应位置上的数字是一样的,而不是通过计算来进行比较,直接比较对应位置上的数字即可。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <iostream>

using namespace std;

int main()
{
int i, n;
cin >> n;
for (i = 10000; i < 100000; i++)
{
int a = i / 10000;
int b = (i % 10000) / 1000;
int c = (i % 1000) / 100;
int d = (i % 100) / 10;
int e = i % 10;
if (a == e && b == d && a + b + c + d + e == n)
cout << i << endl;
}
for (i = 100000; i < 1000000; i++)
{
int a = i / 100000;
int b = (i % 100000) / 10000;
int c = (i % 10000) / 1000;
int d = (i % 1000) / 100;
int e = (i % 100) / 10;
int f = i % 10;
if (a == f && b == e && c == d && a + b + c + d + e + f == n)
cout << i << endl;
}

return 0;
}

十六进制转十进制

题目描述

从键盘输入一个不超过8位的正的十六进制数字符串,将它转换为正的十进制数后输出。 注:十六进制数中的10~15分别用大写的英文字母A、B、C、D、E、F表示。

输入解释

十六进制数字符串

输出解释

十进制数

输入样例

1
FFFF

输出样例

1
65535

思路

先将十六进制数转为二进制,再从二进制转为十进制,不失为一个可行的方法。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#include <iostream>
#include <stdlib.h>

using namespace std;

string GetBin(string s)
{
string re;
int count = s.length();
for (int i = 0; i < count; i++)
{
switch (s[i])
{
case '0':
re += "0000";
break;
case '1':
re += "0001";
break;
case '2':
re += "0010";
break;
case '3':
re += "0011";
break;
case '4':
re += "0100";
break;
case '5':
re += "0101";
break;
case '6':
re += "0110";
break;
case '7':
re += "0111";
break;
case '8':
re += "1000";
break;
case '9':
re += "1001";
break;
case 'A':
re += "1010";
break;
case 'B':
re += "1011";
break;
case 'C':
re += "1100";
break;
case 'D':
re += "1101";
break;
case 'E':
re += "1110";
break;
case 'F':
re += "1111";
break;
default:
break;
}
}

return re;
}

long long GetDec(string s)
{
long long re = 0;
long long count = s.length(), num = 1;
for (int i = count - 1; i >= 0; i--)
{
re += (s[i] - '0') * num;
num *= 2;
}

return re;
}

int main()
{
string s = "";
cin >> s;
int len = s.length();
int num = 1;
string t = GetBin(s);
long long re = GetDec(t);
cout << re << endl;

return 0;
}

需要注意的地方就是八位十六进制数其实是一个很大的数,long long类型比较稳妥,还有这里我之前用的是pow()函数,后来换成累乘2,这个地方累乘的2要注意数据范围,因为也会变得特别大,之前用int类型就出错了,这个地方需要注意。

当然也有投机取巧的方法,就是利用C/C++自带的格式控制输出,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// C语言版
#include <stdio.h>

int main()
{
unsigned int n;
scanf("%X", &n);
printf("%u", n);
return 0;
}

// C++版
#include <iostream>
#include <iomanip>

using namespace std;

int main()
{
unsigned int n;
cin >> hex >> n;
cout << dec << n << endl;
return 0;
}

2021.3.28更。

最近事情有点多,状态不是很好,会慢慢调整过来的,加油!

十六进制转八进制

题目描述

给定n个十六进制正整数,输出它们对应的八进制数。

输入解释

输入的第一行为一个正整数n (1<=n<=10)。 接下来n行,每行一个由0-9、大写字母A-F组成的字符串,表示要转换的十六进制正整数,每个十六进制数长度不超过100000。

输出解释

输出n行,每行为输入对应的八进制正整数。

输入样例

1
2
3
2
39
123ABC

输出样例

1
2
71
4435274

提示 先将十六进制数转换成某进制数,再由某进制数转换成八进制。

思路

因为题目提示先将十六进制数转换为某进制数,然后再转换为八进制数。如果说我们正常做题的思维,可能会将十六进制数先转换为二进制,然后再转换为八进制,但这样的话其实实现起来很麻烦。但如果考虑到C语言自带的格式控制,我们可以将十进制数直接输出为八进制的格式,这样就会方便很多。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <stdio.h>
#include <string.h>

// 十六进制字符转数字
int x2i(char c)
{
if (c >= 'A')
return c - 55;
else
return c - 48;
}

int main()
{
int i, j, n;
char a[10][100001];
scanf("%d", &n);
for (i = 0; i < n; i++)
scanf("%s", a[i]);
for (i = 0; i < n; i++)
{
char *p = a[i];
int len = strlen(p);
// 若字符串长度/3余1个,则先将那个单独考虑
if (len % 3 == 1)
{
// 先转换成十进制,再用%o输出八进制
printf("%o", x2i(p[0]));
j = 1;
}
// 先将两个单独考虑
else if (len % 3 == 2)
{
printf("%o", x2i(p[0]) * 16 + x2i(p[1]));
j = 2;
}
// 三的倍数的时候直接操作,每三位进行操作
else
{
printf("%o", x2i(p[0]) * 256 + x2i(p[1]) * 16 + x2i(p[2]));
j = 3;
}
for (; j < len; j += 3)
printf("%04o", x2i(p[j]) * 256 + x2i(p[j + 1]) * 16 + x2i(p[j + 2]));
printf("\n");
}
return 0;
}

数列排序

题目描述

给定一个长度为n的数列,将这个数列按从小到大的顺序排列。1<=n<=200

输入解释

第二行包含n个整数,为待排序的数,每个整数的绝对值小于10000。

输出解释

输出一行,按从小到大的顺序输出排序后的数列。

输入样例

1
2
5
8 3 6 4 9

输出样例

1
3 4 6 8 9

思路

思路很简单,就是简单排序,可以选择自己喜欢的各种排序方法,因为数据的个数并不是很多,所以性能最差的排序方法也可以跑出来。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <iostream>

using namespace std;

int main()
{
int len;
cin >> len;
int *a = new int[len];
for (int i = 0; i < len; i++)
{
cin >> a[i];
}

for (int i = 0; i < len - 1; i++)
{
for (int j = i + 1; j < len; j++)
{
if (a[i] > a[j])
{
int t = a[i];
a[i] = a[j];
a[j] = t;
}
}
}

for (int i = 0; i < len; i++)
{
cout << a[i] << " ";
}
cout << endl;

return 0;
}

时间转换

题目描述

给定一个以秒为单位的时间t,要求用“::”的格式来表示这个时间。表示时间,表示分钟,而表示秒,它们都是整数且没有前导的“0”。例如,若t=0,则应输出是“0:0:0”;若t=3661,则输出“1:1:1”。

输入解释

输入只有一行,是一个整数t(0<=t<=86399)。

输出解释

输出只有一行,是以“::”的格式所表示的时间,不包括引号。

输入样例

1
2
3
4
5
NO.1
0

NO.2
5436

输出样例

1
2
3
4
5
NO.1
0:0:0

NO.2
1:30:36

思路

这个时间转换问题本质上其实是一个十进制数转化为六十进制数的问题。记录好需要的数据并不难。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>

using namespace std;

int main()
{
long in;
cin >> in;
int sec = in % 60;
int numOfmin = in / 60;
int min = numOfmin % 60;
int h = numOfmin / 60;
cout << h << ":" << min << ":" << sec << endl;

return 0;
}

字符串对比

题目描述

给定两个仅由大写字母或小写字母组成的字符串(长度介于1到10之间),它们之间的关 系是以下4中情况之一: 1:两个字符串长度不等。比如 Beijing 和 Hebei 2:两个字符串不仅长度相等,而且相应位置上的字符完全一致(区分大小写),比如

Beijing 和 Beijing 3:两个字符串长度相等,相应位置上的字符仅在不区分大小写的前提下才能达到完

全一致(也就是说,它并不满足情况2)。比如 beijing 和 BEIjing 4:两个字符串长度相等,但是即使是不区分大小写也不能使这两个字符串一致。比

如 Beijing 和 Nanjing 编程判断输入的两个字符串之间的关系属于这四类中的哪一类,给出所属的类的编号

输入解释

包括两行,每行都是一个字符串

输出解释

仅有一个数字,表明这两个字符串的关系编号

输入样例

1
2
BEIjing
beiJing

输出样例

1
3

思路

这道题目判断的优先级选择好做起来会方便很多。首先判断字符串长度,长度不等则为情况1,相等则进一步讨论;字符串长度相等时,判断每位字符,如果都相等,则为情况2,否则再进一步讨论;若是大小写的区别,则为情况3,否则为情况4。这里需要注意的就是字符串长度相等时一定要判断到最后一个字符,这样才能知道两个字符串是否完全相等,还是前面几个出现大小写的情况,最后出现字母不一致的情形。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include <iostream>
#include <math.h>

using namespace std;

int main()
{
string str1, str2;
cin >> str1 >> str2;
int lenStr1 = str1.length();
int lenStr2 = str2.length();
// flag区分全部相等与仅是大小写区别。
int flag = 0;
if (lenStr1 != lenStr2)
{
cout << 1 << endl;
}
else
{
for (int i = 0; i < lenStr1; i++)
{
if (str1[i] == str2[i])
{

}
else
{
if (abs(str1[i] - str2[i]) == 32)
{
flag = 1;
continue;
}
else
{
cout << 4 << endl;
return 0;
}
}
}
if (flag)
{
cout << 3 << endl;
}
else
{
cout << 2 << endl;
}
}

system("pause");
return 0;
}

2021.3.29 更

分解质因数

题目描述

求出区间[a,b]中所有整数的质因数分解。

输入解释

输入两个整数a,b。

输出解释

每行输出一个数的分解,形如k=a1a2a3...(a1<=a2<=a3...,k也是从小到大的)(具体可看样例)

输入样例

1
3 10  

输出样例

1
2
3
4
5
6
7
8
3=3  
4=2*2
5=5
6=2*3
7=7
8=2*2*2
9=3*3
10=2*5

提示 先筛出所有素数,然后再分解。 数据规模和约定 2<=a<=b<=10000

思路

这道题目并不难,很中规中矩的题目。外循环遍历每个值,内循环就是输出。根据题目的提示,先找出质数,质数直接输出,然后对非质数进行操作就好了。我的代码有个问题就是用了cout运行时间过长,不知道是bug还是什么原因,改用scanf()就没有报错了。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#include <iostream>
#include <math.h>

using namespace std;

int IsPrime(int n)
{
int up = sqrt(n);
for (int i = 2; i <= up; i++)
{
if (n % i == 0)
{
return 0;
}
}
return 1;
}

int main()
{
// a——左界,b——右界
int a, b;
cin >> a >>b;

for (int i = a; i <= b; i++)
{
int x = i;
int t = 2;
int star = 1;
cout << x << "=";
if (IsPrime(i))
{
cout << i << endl;
}
else
{
while (x / t)
{
if (x % t == 0)
{
printf("%d", t);
// 控制"*"的输出
if (x / t == 1)
{
star = 0;
}
if (star)
{
printf("*");
}
x = x / t;
}
else
{
t++;
}
}
star = 1;
printf("\n");
}
}

return 0;
}

2021.3.30更

矩阵相乘

题目描述

给定一个N阶矩阵A,输出A的M次幂(M是非负整数) 例如: A = 1 2 3 4 A的2次幂 7 10 15 22

输入解释

  第一行是一个正整数N、M(1<=N<=30, 0<=M<=5),表示矩阵A的阶数和要求的幂数 接下来N行,每行N个绝对值不超过10的非负整数,描述矩阵A的值

输出解释

  输出共N行,每行N个整数,表示A的M次幂所对应的矩阵。相邻的数之间用一个空格隔开

输入样例

1
2
3
2 2
1 2
3 4

输出样例

1
2
7 10
15 22

思路

像输入的数据是多维矩阵的形式,如果阶数存在上限,那么我们可以直接申请二维数组,并且利用矩阵的维数就是上限值,因为这时候极大可能每个样例都会输入一个上限值,这样就避免了使用new运算符申请多维数组比较麻烦的问题。

该题利用二维数组解决会非常方便,使用矩阵乘法的定义即可。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#include <iostream>
#include <stdio.h>
#include <string.h>

using namespace std;

int main()
{
int n, m;
cin >> n >> m;
// a为输入的矩阵,b是每次运算的累乘矩阵,re是结果矩阵
int a[30][30] = {0}, b[30][30] = {0}, re[30][30] = {0};
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
cin >> a[i][j];
}
}
// b的初始化,为了第一次的操作,需要b第一次操作之后成为输入的那个矩阵
for (int j = 0; j < n; j++)
re[j][j] = 1;
for (int num = 0; num < m; num++)
{
// 每次操作b也需要归零
memset(b, 0, sizeof(b));
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
for (int k = 0; k < n; k++)
{
// 该步骤不能出错
b[i][j] += re[i][k] * a[k][j];
}
}
}
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
re[i][j] = b[i][j];
}
}
}
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
cout << re[i][j] << " ";
}
cout << endl;
}

return 0;
}

2021.3.31更

矩形面积交

题目描述

平面上有两个矩形,它们的边平行于直角坐标系的X轴或Y轴。对于每个矩形,我们

给出它的一对相对顶点的坐标,请你编程算出两个矩形的交的面积。

输入解释

输入仅包含两行,每行描述一个矩形。 在每行中,给出矩形的一对相对顶点的坐标,每个点的坐标都用两个绝对值不超过10^7的实数表示。

输出解释

输出仅包含一个实数,为交的面积,保留到小数后两位。

输入样例

1
2
1 1 3 3
2 2 4 4

输出样例

1
1.00

思路

这道题目之前好像做过,但是没做出来,想了一会儿思路比较乱,索性就不自己想了,在网上找到一篇很好文章,在这里也分享给大家。

矩形面积交[蓝桥杯]

题目中只说了给出一对相对顶点的坐标,但题目中并没有说给出的是主对角线还是副对角线,为了不用分类讨论,根据矩形的性质,我们可以根据主对角线的点坐标推出次对角线的点坐标。

1
2
3
4
5
6
7
8
9
我们先假设先输入的一对相对顶点坐标分别为 x1,y1,x2,y2
我们假设这个矩形右上角的坐标点为 x,y
我们假设这个矩形左下角的坐标点为 xx,yy
那么矩形右上角的坐标点:
x = max(x1, x2)
y = max(y1, y2)
同理矩形左下角的坐标点
xx = min(x1, x2)
yy = min(y1, y2)
主对角线与副对角线

借此我们可以求出输入的矩阵的右上角与左下角的坐标。接下来便可以计算相交矩阵的右上角与左下角的点坐标了。

相交矩阵次对角线的点坐标
1
2
相交矩形的左下角坐标点 = 两矩形左下角坐标点最大的那个
相交矩形的右上角坐标点 = 两矩形右上角坐标点最小的那个

那么我们便可以写出相交矩阵的相对点的坐标了

1
2
3
4
a1 = max(min(x1, x2), min(x3, x4)); //相交矩形的左下角x坐标
b1 = max(min(y1, y2), min(y3, y4)); //相交矩形的左下角y坐标
a2 = min(max(x1, x2), max(x3, x4)); //相交矩形的右上角x坐标
b2 = min(max(y1, y2), max(y3, y4)); //相交矩形的右上角y坐标

这时工作并没有结束,我们只考虑了矩阵相交的情况,可是如果矩阵没有相交是什么情况呢?

结合上图,可以观察出:只有(a1 < a2 && b1 < b2)这样才相交,否者两矩形就是没有相交,输出0.00即可。

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <iomanip>
using namespace std;
int main()
{
double x1, y1, x2, y2;
double x3, y3, x4, y4;
double a1, b1, a2, b2; //相交矩形的对角坐标点
while (cin >> x1 >> y1 >> x2 >> y2)
{
cin >> x3 >> y3 >> x4 >> y4;
a1 = max(min(x1, x2), min(x3, x4)); //相交矩形的左下角x坐标
b1 = max(min(y1, y2), min(y3, y4)); //相交矩形的左下角x坐标
a2 = min(max(x1, x2), max(x3, x4)); //相交矩形的右上角x坐标
b2 = min(max(y1, y2), max(y3, y4)); //相交矩形的右上角x坐标
double area = 0;
area = (a2 - a1) * (b2 - b1);
if (a1 < a2 && b1 < b2)
cout << fixed << setprecision(2) << area << endl;
else
cout << "0.00" << endl;
}

return 0;
}

2020.4.5更

完美的代价

题目描述

回文串,是一种特殊的字符串,它从左往右读和从右往左读是一样的。小龙龙认为回文串才是完美的。现在给你一个串,它不一定是回文的,请你计算最少的交换次数使得该串变成一个完美的回文串。 交换的定义是:交换两个相邻的字符 例如mamad 第一次交换 ad : mamda 第二次交换 md : madma 第三次交换 ma : madam (回文!完美!)

输入解释

第一行是一个整数N,表示接下来的字符串的长度(N <= 8000) 第二行是一个字符串,长度为N.只包含小写字母

输出解释

如果可能,输出最少的交换次数。 否则输出Impossible

输入样例

1
2
5
mamad

输出样例

1
3

思路

对于回文串,里面的字符要么都是成对存在的,要么有且只有一个字符出现奇数次。因此要判断一个字符能不能旋转成为回文串字符串,要先判断其中的字符是否符合条件,然后再观察其中字符的排列,进行字符的交换。思路是有的,但还是做不出来,以下是网上找到的一个很好的代码。

原文链接:蓝桥杯 (基础练习) 完美的代价 C语言

原文思路:

定义i和j两个变量,分别指向回文串的首部和尾部,将i从左向右开始遍历,j从右向左开始遍历。 在每次查找的过程中,让i不变,j从后往前移动,直到找到和i相等的值,找到后,将找到的字母依次向后移动,移动到初始j的位置。并记录下移动的次数。 注意:在查找的过程中会有异常情况,即移动到i的后面一个位置还没有找到和i相等的字母,这时就出现了唯一值(wy)的情况,即整个串该字母只出现了一次。 简单分析就知道,当串的长度为双数时,出现一个唯一值(wy)则一定构不成回文串;当串的长度为单数时,也最多有一个唯一值(wy),否则也构不成回文串。 !!!当只有一个唯一值(wy)并且串的长度为单数(此时这个唯一值只能放在串的中间位置),当我们找到这个唯一值(wy)时,不应该立即把它移动到串的中间,因为如果立即移动到串的中间时,在后面的查找移动交换的过程中,又会将该唯一值(wy)从中间移走,最后还得重新把它移到中间,这样就增加了移动步数。所以可以将这个唯一值进行记录,记录下该唯一值最终的移动步数=N/2(串长度的一半)+1-i,然后跳过该唯一值(wy),i加1,继续下一次循环。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
// 我吐了,我可能真的是比较笨,我怎么就写不出来这道题目,呜呜呜呜呜呜,突然感觉自己还是个菜鸡。唉,路漫漫其修远兮,吾将上下而求索。
// 可不能因为有了对象,就影响你拔剑啊
#include <stdio.h>
int main()
{
int N;
scanf("%d\n", &N);
char a[N + 1]; //习惯数组从1开始,所以我定义了N+1个空间
int i;
for (i = 1; i <= N; i++)
{
scanf("%c", &a[i]);
}
// j为从后往前的那个变量
int j = N;
// t用来暂存j的值,因为j会变化
int t;
// sum就是交换的次数
int sum = 0;
// wy定义出现唯一值的个数
int wy = 0;
char bc, yd;
int s;
for (i = 1; (i <= N / 2 + 1) && (j > i); i++)
{
t = j; // 因为在后面j的值会发生变化,所以将j另存
while (a[i] != a[j]) // 找到与a[i]相等字母的下标j
{
j--;
}
if (j == i) //判断当出现唯一的数的特殊情况
{
wy++; //出现一次,唯一(wy)的值就加1
if ((wy == 1) && (N % 2 == 0)) //当为双数时,不能出现(wy)
{
printf("Impossible");
return 0;
break;
}
else if (wy > 1) //单数的(wy)也最多只能出现一次,如果大于1时,则不能构成回文数
{
printf("Impossible");
return 0;
break;
}
else
{
bc = a[i];
j = t;
sum = sum + N / 2 + 1 - i;
continue;
}
/*上面的else块是为单数并且(wy)等于1时的情况,这时的处理方法不是立即移动(wy),而是暂存记录,最后做移动,
(在这一题只是让输出移动步数,所以最后也不必真正移动)只需要记录移动的总步数 */
}
else //正常的移动步骤
{
for (s = j; s < t; s++)
{
yd = a[s];
a[s] = a[s + 1];
a[s + 1] = yd;
sum++;
}
j = t - 1;
}
}
printf("%d", sum);

return 0;
}

数的读法

题目描述

Tom教授正在给研究生讲授一门关于基因的课程,有一件事情让他颇为头疼:一条染色体上有成千上万个碱基对,它们从0开始编号,到几百万,几千万,甚至上亿。 比如说,在对学生讲解第1234567009号位置上的碱基时,光看着数字是很难准确的念出来的。 所以,他迫切地需要一个系统,然后当他输入12 3456 7009时,会给出相应的念法: 十二亿三千四百五十六万七千零九 用汉语拼音表示为 shi er yi san qian si bai wu shi liu wan qi qian ling jiu 这样他只需要照着念就可以了。 你的任务是帮他设计这样一个系统:给定一个阿拉伯数字串,你帮他按照中文读写的

规范转为汉语拼音字串,相邻的两个音节用一个空格符格开。 注意必须严格按照规范,比如说“10010”读作“yi wan ling yi shi”而不是“yi wan ling shi”,“100000”读作“shi wan”而不是“yi shi wan”,“2000”读作“er qian”而不是“liang qian”。

输入解释

有一个数字串,数值大小不超过2,000,000,000。

输出解释

是一个由小写英文字母,逗号和空格组成的字符串,表示该数的英文读法。

输入样例

1
1234567009

输出样例

1
shi er yi san qian si bai wu shi liu wan qi qian ling jiu

思路

阿西,这个我不太会,qaq,网上也没找到好的解法,好多要么没有思路,要么思路看不懂,等我再研究研究再补上去!!!先把网上看到的代码放上去吧。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <stdio.h>

int main()
{
char* num[] = {"ling","yi","er","san","si","wu","liu","qi","ba","jiu"};
char* wei[] = {"shi","bai","qian","wan","yi"};
char* str[20];
int n;
scanf("%d", &n);
int i = 0, j = 0, k, l[2] = {0};
while (n > 0)
{
k = n % 10;
n /= 10;
if (k > 0) {
if (i > 0)
{
if (i >= 4 && !l[i / 4 - 1]) l[i / 4 - 1] = 1, str[j++] = wei[i / 4 + 2];
if (i % 4 != 0) str[j++] = wei[i % 4 - 1];
}
str[j++] = num[k];
} else if (j > 0 && str[j - 1] != num[0]) {
str[j++] = num[0];
}
i++;
}
if (!(str[j - 1] == num[1] && j > 1 && str[j - 2] == wei[0]))
printf("%s ", str[j - 1]);
for (i = j - 2; i >= 0; i--)
printf("%s ", str[i]);
return 0;
}

最近跟女朋友玩的太多了......果然女人就会影响我们拔刀的速度呀,不过真的好喜欢宝贝,哈哈哈哈哈哈哈哈哈,努力!!!

2021.4.11更

Sine之舞

题目描述

最近FJ为他的奶牛们开设了数学分析课,FJ知道若要学好这门课,必须有一个好的三角函数基本功。所以他准备和奶牛们做一个“Sine之舞”的游戏,寓教于乐,提高奶牛们的计算能力。 不妨设 An=sin(1–sin(2+sin(3–sin(4+...sin(n))...) Sn=(...(A1+n)A2+n-1)A3+...+2)An+1 FJ想让奶牛们计算Sn的值,请你帮助FJ打印出Sn的完整表达式,以方便奶牛们做题。

输入解释

仅有一个数:N<201。

输出解释

请输出相应的表达式Sn,以一个换行符结束。输出中不得含有多余的空格或换行、回车符。

输入样例

1
3

输出样例

1
((sin(1)+3)sin(1–sin(2))+2)sin(1–sin(2+sin(3)))+1

思路

这代题目乍一看没看懂,但其实慢慢分析会发现其实很简单。

首先讨论An,先看看An的构成:

  • A1 = sin(1)

  • A2 = sin(1-sin(2))

  • A3 = sin(1-sin(2+sin(3)))

    ......

    写出三个便可以看出一点规律性:

    比如在A3中,我们将A3划分为sin(1-,sin(2+,sin(3,)))这四个部分,前三个都带有sin(这个部分,1,2,3可以通过循环变量i进行改变,范围为1-n(下标值)+,-的变化可以与i挂钩,那么这种形式的规律我们就找到了,而)))则与下标3挂钩,用一个循环输出即可。

现在看Sn,也看看Sn的构成:

  • S1 = sin(1)+1

  • S2 = (sin(1)+2)sin(1-sin(2))+1

  • S3 = ((sin(1)+3)sin(1-sin(2))+2)sin(1-sin(2+sin(3)))+1

    ......

    同样写出三个也可以看出部分规律性:

    以S3为例:S3可以划分为((,A1+3),A2+2),A3+1四个部分,那么((可以与下标n建立关系,遍历输出n-1个即可;后面的部分,只要下标值不等于n,统一的形式就是Ai+n-i+1),下标值in时,不输出最后的括号即可,那么我们就可以根据思路写出代码了。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#include <iostream>
#include <string>
#include <math.h>

using namespace std;

string An(int count)
{
string res;

for (int i = 1; i <= count; i++)
{
// cout << sin << zuo << i;
res += "sin(";
res += to_string(i);
if (i != count)
{
if (i % 2 == 0)
{
res += "+";
// cout << "+";
}
else
{
res += "-";
// cout << "-";
}
}
}
for (int i = 0; i < count; i++)
{
res += ")";
// cout << you;
}
// cout << endl;

return res;
}

string Sn(int count)
{
string res;
for (int i = 1; i < count; i++)
{
printf("(");
}
// 我这里用另一个变量暂存了count的值,比较简单,也可以使用上述思路里的n-i+1
int n = count;
for (int i = 1; i <= count; i++)
{
res += An(i) + "+" + to_string(n--);
if (i != count)
{
res += ")";
}
}

return res;
}

int main()
{
int n;
cin >> n;
// cout << "An:" << An(n) << endl;
cout << Sn(n) << endl;

system("pause");
return 0;
}

本题目中用了一个很好用的一个函数to_string(),这个函数可以将很多种类型的变量值转换为string类型,具体如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
string to_string (int val);

string to_string (long val);

string to_string (long long val);

string to_string (unsigned val);

string to_string (unsigned long val);

string to_string (unsigned long long val);

string to_string (float val);

string to_string (double val);

string to_string (long double val);

FJ的字符串

题目描述

FJ在沙盘上写了这样一些字符串: A1 = “A” A2 = “ABA” A3 = “ABACABA” A4 = “ABACABADABACABA” … … 你能找出其中的规律并写所有的数列AN吗?

输入解释

仅有一个数:N ≤ 26。

输出解释

请输出相应的字符串AN,以一个换行符结束。输出中不得含有多余的空格或换行、回车符。

输入样例

1
3

输出样例

1
ABACABA

思路

观察一下,A1从A开始,而A2=A1+B+A1,A3=A2+C+A2,...以此类推即可。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>

using namespace std;

int main()
{
string s26 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
int count;
cin >> count;
string res = "";
string temp = "";
int index = 0;
for (int i = 0; i < count; i++)
{
res =temp + s26[index++] + temp;
temp = res;
}
cout << res << endl;

system("pause");
return 0;
}

芯片测试

题目描述

有n(2≤n≤20)块芯片,有好有坏,已知好芯片比坏芯片多。 每个芯片都能用来测试其他芯片。用好芯片测试其他芯片时,能正确给出被测试芯片是好还是坏。而用坏芯片测试其他芯片时,会随机给出好或是坏的测试结果(即此结果与被测试芯片实际的好坏无关)。 给出所有芯片的测试结果,问哪些芯片是好芯片。

输入解释

输入数据第一行为一个整数n,表示芯片个数。 第二行到第n+1行为n*n的一张表,每行n个数据。表中的每个数据为0或1,在这n行中的第i行第j列(1≤i, j≤n)的数据表示用第i块芯片测试第j块芯片时得到的测试结果,1表示好,0表示坏,i=j时一律为1(并不表示该芯片对本身的测试结果。芯片不能对本身进行测试)。

输出解释

按从小到大的顺序输出所有好芯片的编号

输入样例

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

输出样例

1
1 3

思路

因为题目中所说好芯片比坏芯片多,所以说只要根据每一列的所有测试结果的和,如果这个和大于芯片个数的一半,便说明这个芯片是好芯片。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <iostream>

using namespace std;

int main()
{
int array[21][21];
int n;
cin >> n;
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
cin >> array[i][j];
}
}
for (int i = 1; i <= n; i++)
{
int ts = 0;
for (int j = 1; j <= n; j++)
{
ts += array[j][i];
}
if (ts > n / 2)
{
cout << i << " ";
}
}

return 0;
}

2021.4.21更

龟兔赛跑预测

题目描述

话说这个世界上有各种各样的兔子和乌龟,但是研究发现,所有的兔子和乌龟都有一个共同的特点——喜欢赛跑。于是世界上各个角落都不断在发生着乌龟和兔子的比赛,小华对此很感兴趣,于是决定研究不同兔子和乌龟的赛跑。他发现,兔子虽然跑比乌龟快,但它们有众所周知的毛病——骄傲且懒惰,于是在与乌龟的比赛中,一旦任一秒结束后兔子发现自己领先t米或以上,它们就会停下来休息s秒。对于不同的兔子,t,s的数值是不同的,但是所有的乌龟却是一致——它们不到终点决不停止。 然而有些比赛相当漫长,全程观看会耗费大量时间,而小华发现只要在每场比赛开始后记录下兔子和乌龟的数据——兔子的速度v1(表示每秒兔子能跑v1米),乌龟的速度v2,以及兔子对应的t,s值,以及赛道的长度l——就能预测出比赛的结果。但是小华很懒,不想通过手工计算推测出比赛的结果,于是他找到了你——清华大学计算机系的高才生——请求帮助,请你写一个程序,对于输入的一场比赛的数据v1,v2,t,s,l,预测该场比赛的结果。

输入解释

输入只有一行,包含用空格隔开的五个正整数v1,v2,t,s,l,其中(v1,v2<=100;t<=300;s<=10;l<=10000且为v1,v2的公倍数)

输出解释

输出包含两行,第一行输出比赛结果——一个大写字母“T”或“R”或“D”,分别表示乌龟获胜,兔子获胜,或者两者同时到达终点。 第二行输出一个正整数,表示获胜者(或者双方同时)到达终点所耗费的时间(秒数)。

输入样例 1

1
10 5 5 2 20

输出样例 1

1
2
D
4

输入样例 2

1
10 5 5 1 20

输出样例 2

1
2
R
3

输入样例 3

1
10 5 5 3 20

输出样例 3

1
2
T
4

提示

注意:

样例输入输出分别有三组数据,程序每次运行计算一组数据即可,不需要全部读入后输出

思路

按照正常的思路来解题,兔子跑的距离l1与乌龟跑的距离l2等于l时,赛跑结束。接下来就是计算其相应的跑步距离。乌龟跑步的距离很简单,只需要一直v2 * time即可。兔子的相对来说复杂一点,兔子休息的时候只有乌龟在跑,这个时候要处理好相应的情况即可。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#include <iostream>

using namespace std;

int main()
{
int l, t, s, v1, v2, n = 0, time = 1, l1 = 0, l2 = 0;
// rnum代表兔子休息的时间
int rnum = 0;
cin >> v1 >> v2 >> t >> s >> l;
while (l1 < l && l2 < l)
{
// 奔跑的处理
if (l1 - l2 >= t)
{
// 这个地方就是兔子在休息,乌龟在跑需要注意条件l2 < l
while (rnum < s && l2 < l)
{
l2 = v2 * time;
time++;
rnum++;
}
rnum = 0;
n++;
}
else
{
if (time > s)
{
l1 = v1 * (time - n * s);
}
else
{
l1 = v1 * time;
}
l2 = v2 * time;
time++;
}
}
if (l1 == l && l2 == l)
{
cout << "D" << endl << time - 1 << endl;
}
else if (l1 >= l)
{
cout << "R" << endl << time - 1 << endl;
}
else
{
cout << "T" << endl << time - 1 << endl;
}

return 0;
}

回形取数

题目描述

回形取数就是沿矩阵的边取数,若当前方向上无数可取或已经取过,则左转90度。一开始位于矩阵左上角,方向向下。

输入解释

输入第一行是两个不超过200的正整数m, n,表示矩阵的行和列。接下来m行每行n个整数,表示这个矩阵。

输出解释

输出只有一行,共mn个数,为输入矩阵回形取数得到的结果。数之间用一个空格分隔,行末不要有多余的空格。

输入样例

1
2
3
4
5
6
7
8
9
10
11
No.1
3 3
1 2 3
4 5 6
7 8 9

No.2
3 2
1 2
3 4
5 6

输出样例

1
2
3
4
5
No.1
1 4 7 8 9 6 3 2 5

No.2
1 3 5 6 4 2

思路

代码


蓝桥杯练习
https://excelius.xyz/蓝桥杯练习/
作者
Ther
发布于
2021年3月22日
许可协议