13年12月CCF计算机软件能力认证
3192. 出现次数最多的数
给定
n
n
n个正整数,找出它们中出现次数最多的数。
如果这样的数有多个,请输出其中最小的一个。
输入格式
输入的第一行只有一个正整数
n
n
n,表示数字的个数。
输入的第二行有
n
n
n个整数
s
1
,
s
2
,
…
,
s
n
s_1,s_2,\ldots,s_n
s1,s2,…,sn 。
相邻的数用空格分隔。
输出格式
输出这
n
n
n个次数中出现次数最多的数。
如果这样的数有多个,输出其中最小的一个。
数据范围
1 ≤ n ≤ 1000 , 1 ≤ s i ≤ 10000 \begin{aligned}&1\leq n\leq1000,\\&1\leq s_i\leq10000\end{aligned} 1≤n≤1000,1≤si≤10000
输入样例:
6
10110203020
输出样例:
10
}
数组模拟
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int c[N];
int n;
int mx = 1e5 + 10, cnt;
int main()
{
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin >> n;
while (n -- )
{
int x;
cin >> x;
c[x] ++;
if(c[x] > cnt)
{
cnt = c[x];
mx = x;
}
if(c[x] == cnt && x < mx)
mx = x;
}
cout << mx << endl;
return 0;
}
Map
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int mx = N, cnt;
int n;
map<int, int> mp;
int main()
{
cin >> n;
while (n -- )
{
int x;
cin >> x;
mp[x] ++;
if(mp[x] > cnt)
{
cnt = mp[x];
mx = x;
}
if(mp[x] == cnt && x < mx)
mx = x;
}
cout << mx << endl;
return 0;
}
3193. ISBN号码
每一本正式出版的图书都有一个 ISBN 号码与之对应。
ISBN 码包括9位数字、1位识别码和3位分隔符,其规定格式如 x-xxx-xxxxx-x ,其中符号 - 是分隔符 (键盘上的减号),最后一位是识别码,例如 0-670-82162-4 就是一个标准的ISBN码。
ISBN 码的首位数字表示书籍的出版语言,例如0代表英语;第一个分隔符 - 之后的三位数字代表出版社,例如670代表维京出版社;第二个分隔之后的五位数字代表该书在出版社的编号;最后一位为识别码。
识别码的计算方法如下:
首位数字乘以1加上次位数字乘以2…以此类推,用所得的结果mod 11,所得的余数即为识别码,如果余数为 10,则识别码为大写字母
X
.
X.
X.
例如ISBN 号码 0-670-82162-4 中的识别码4是这样得到的:对067082162这 9 个数字,从左至右,分别乘以
1
,
2
,
…
,
9
1,2,\ldots,9
1,2,…,9,再求和,即
0
×
1
+
6
×
2
+
…
…
+
2
×
9
=
158
0\times1+6\times2+\ldots\ldots+2\times9=158
0×1+6×2+……+2×9=158,然后取158 mod 11的结果 4 作为识别码。
编写程序判断输入的 ISBN 号码中识别码是否正确,如果正确,则仅输出 Right;如果错误,则输出是正确的ISBN 号码。
输入格式
输入只有一行,是一个字符序列,表示一本书的 ISBN 号码 (保证输入符合 ISBN 号码的格式要求)。
输出格式
输出一行,假如输入的ISBN 号码的识别码正确,那么输出 Right,否则,按照规定的格式,输出正确的 ISBN号码(包括分隔符 -)。
输入样例1:
0-670-82162-4
输出样例1:
Right
输入样例2:
0-670-82162-0
输出样例2:
0-670-82162-4
#include <bits/stdc++.h>
using namespace std;
int main()
{
string s;
cin >> s;
for(int i = 0; i < s.size(); i ++)
if(s[i] == '-')
s.erase(i, 1);
int res = 0;
for(int i = 0; i < s.size() - 1; i ++)
res += (s[i] - '0') * (i + 1);
int m = res % 11;
if(m == s[s.size() - 1] - '0')
cout << "Right" << endl;
else if(m == 10 && s[s.size() - 1] == 'X')
cout << "Right" << endl;
else
{
for(int i = 0; i < s.size() - 1; i ++)
{
cout << s[i];
if(i == 0 || i == 3 || i == 8)
cout << '-';
}
if(m == 10)
cout << 'X';
else
cout << m;
}
return 0;
}
3194. 最大的矩形
在横轴上放了
n
n
n个相邻的矩形,每个矩形的宽度是1,而第
i
i
i (
1
≤
i
≤
n
1\leq i\leq n
1≤i≤n)个矩形的高度是
h
i
h_i
hi。
这
n
n
n个矩形构成了一个直方图。
例如,下图中六个矩形的高度就分别是3,1,6,5,2,3.
请找出能放在给定直方图里面积最大的矩形,它的边要与坐标轴平行。对于上面给出的例子,最大矩形如下图所示的阴影部分,面积是10。
输入格式
第一行包含一个整数
n
n
n,即矩形的数量。
第二行包含
n
n
n个整数
h
1
,
h
2
,
…
,
h
n
h_1,h_2,\ldots,h_n
h1,h2,…,hn ,相邻的数之间由空格分隔。
h
i
h_i
hi是第
i
i
i个矩形的高度。
输出格式
输出一行,包含一个整数,即给定直方图内的最大矩形的面积。
数据范围
1 ≤ n ≤ 1000 1\leq n\leq1000 1≤n≤1000, 1 ≤ h i ≤ 10000 1\leq h_i\leq10000 1≤hi≤10000 经实测 h i h_i hi在官网的实际范围是 1 ≤ h i ≤ 40000 1\leq h_i\leq40000 1≤hi≤40000,这与其给出的题面描述不符,属于官网出题人的失误,也因此卡住了一些同学的代码,望大家加以注意。
输入样例:
6
3 1 6 5 2 3
输出样例:
10
#include <bits/stdc++.h>
using namespace std;
const int N = 1010;
int h[N];
int n;
int res;
int main()
{
cin >> n;
for(int i = 1; i <= n; i ++)
cin >> h[i];
for(int i = 1; i <= n; i ++)
{
int l, r;
for(int j = i; j >=1; j --)
{
if(h[i] > h[j]) break;
l = j;
}
for(int j = i; j <= n; j ++)
{
if(h[i] > h[j]) break;
r = j;
}
res = max(res, h[i] * (r - l + 1));
}
cout << res << endl;
return 0;
}
3195. 有趣的数
我们把一个数称为有趣的,当且仅当:
1.它的数字只包含0,1,2,3 ,且这四个数字都出现过至少一次。
2.所有的0都出现在所有的 1 之前,而所有的2都出现在所有的 3 之前。
3.最高位数字不为0。
因此,符合我们定义的最小的有趣的数是 2013
除此以外,4位的有趣的数还有两个:2031 和2301。
请计算恰好有 n n n位的有趣的数的个数。
由于答案可能非常大,只需要输出答案除以 1 0 9 + 7 10^9+7 109+7的余数。
输入格式
输入只有一行,包括恰好一个正整数 n n n。
输出格式
输出只有一行,包括恰好 n n n位的整数中有趣的数的个数除以 1 0 9 + 7 10^9+7 109+7的余数。
数据范围
4
≤
n
≤
1000
4\leq n\leq1000
4≤n≤1000
输入样例:
4
输出样例:
3
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1010, mod = 1e9 + 7;
int n, c[N][N];
LL res;
int main()
{
cin >> n;
for(int i = 0; i <= n; i ++)
for(int j = 0; j <= i; j ++)
if(!j) c[i][j] = 1;
else c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % mod;
for(int k = 2; k <= n - 2; k ++)
res = (res + (LL)c[n - 1][k] * (k - 1) * (n - k - 1)) % mod;
cout << res << endl;
return 0;
}
3196. I’m stuck!
给定一个 R R R行 C C C列的地图,地图的每一个方格可能是 #,+,-,1,.,s,T 七个字符中的一个,分别表
示如下意思:
#
:
\#:
#:任何时候玩家都不能移动到此方格;
· + :当玩家到达这一方格后,下一步可以向上下左右四个方向相邻的任意一个非 # 方格移动一格;
· - :当玩家到达这一方格后,下一步可以向左右两个方向相邻的一个非 # 方格移动一格; · |!当玩家到达这一方格后,下一步可以向上下两个方向相邻的一个非 # 方格移动一格; ····当玩家到达这一方格后,下一步只能向下移动一格。如果下面相邻的方格为 #,则玩家不能再移动;
· S:玩家的初始位置,地图中只会有一个初始位置。玩家到达这一方格后,下一步可以向上下左右四个方向相邻的任意一个非#方格移动一格;
· T:玩家的目标位置,地图中只会有一个目标位置。玩家到达这一方格后,可以选择完成任务,也可以选择不完成任务继续移动。如果继续移动下一步可以向上下左右四个方向相邻的任意一个非 # 方格移动一格。
此外,玩家不能移动出地图。
请找出满足下面两个性质的方格个数:
玩家可以从初始位置移动到此方格; 2.玩家不可以从此方格移动到目标位置。
输入格式
输入的第一行包括两个整数
R
R
R和
C
C
C,分别表示地图的行和列数
接下来的
R
R
R行每行都包含
C
C
C个字符。它们表示地图的格子。地图上恰好有一个 s 和一个 T。
输出格式
如果玩家在初始位置就已经不能到达终点了,就输出 I’m stuck! 。
否则的话,输出满足性质的方格的个数。
数据范围
1
≤
R
,
C
≤
50
1\leq R,C\leq50
1≤R,C≤50
输入样例:
55
–±+
… ∣ # . \ldots|_{\#}. …∣#.
… ∣ # # \ldots|_{\#\#} …∣##
s − + − T s-+-T s−+−T
# # # # . \#\#\#\#. ####.
输出样例:
2
样例解释
如果把满足性质的方格在地图上用 x 标记出来的话,地图如下所示:
–±+
… ∣ # X \ldots|\#X …∣#X
… ∣ # # \ldots|_{\#\#} …∣##
S − + − T S-+-T S−+−T
# # # # X \#\#\#\#X ####X
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 55;
int n, m;
int st1[N][N], st2[N][N];
char g[N][N];
int tx, ty;
int dx[] = {-1, 0, 1, 0}, dy[] = {0, 1, 0 , -1};
int res;
bool check(int x, int y, int k)
{
char c = g[x][y];
if(c == '+' || c == 'S' || c == 'T') return true;
if(c == '|' && k % 2 == 0) return true;
if(c == '-' && k % 2 == 1) return true;
if(c == '.' && k == 2) return true;
return false;
}
void dfs1(int x, int y)
{
st1[x][y] = true;
for(int i = 0; i < 4; i ++)
{
int a = x + dx[i], b = y + dy[i];
if(a < 0 || a >= n || b < 0 || b >= m || g[a][b] == '#' || st1[a][b]) continue;
if(check(x, y, i))
dfs1(a, b);
}
}
void dfs2(int x, int y)
{
st2[x][y] = true;
for(int i = 0; i < 4; i ++)
{
int a = x + dx[i], b = y + dy[i];
if(a < 0 || a >= n || b < 0 || b >= m || g[a][b] == '#' || st2[a][b]) continue;
if(check(a, b, i ^ 2))
dfs2(a, b);
}
}
int main()
{
cin >> n >> m;
for(int i = 0; i < n; i ++) cin >> g[i];
for(int i = 0; i < n; i ++)
{
for(int j = 0; j < m; j ++)
{
if(g[i][j] == 'S') dfs1(i, j);
else if(g[i][j] == 'T')
{
tx = i, ty = j;
dfs2(i, j);
}
}
}
if(!st1[tx][ty])
cout << "I'm stuck!" << endl;
else
{
for(int i = 0; i < n; i ++)
for(int j = 0; j < m; j ++)
if(st1[i][j] && !st2[i][j])
res ++;
cout << res << endl;
}
return 0;
}
第一次CCF计算机软件能力认证
3197. 相反数
输入格式
有
N
N
N个非零且各不相同的整数。
请你编一个程序求出它们中有多少对相反数(
a
a
a和
−
a
-a
−a为一对相反数)。
第一行包含一个正整数
N
N
N。
第二行为
N
N
N个用单个空格隔开的非零整数,每个数的绝对值不超过1000,保证这些整数各不相同。
输出格式
只输出一个整数,即这
N
N
N个数中包含多少对相反数。
数据范围
1
≤
N
≤
500
1\leq N\leq500
1≤N≤500
输入样例:
5
123-1-2
输出样例:
2
#include <bits/stdc++.h>
using namespace std;
const int N = 1010;
set<int> s;
bool st[N];
int n;
int cnt;
int main()
{
cin >> n;
for(int i = 1; i <= n; i ++)
{
int x;
cin >> x;
s.insert(x);
if(s.count(-x) && !st[abs(x)])
{
st[abs(x)] = true;
cnt ++;
}
}
cout << cnt << endl;
return 0;
}
3198. 窗口
在某图形操作系统中,有
N
N
N个窗口,每个窗口都是一个两边与坐标轴分别平行的矩形区域。
窗口的边界上的点也属于该窗口。
窗口之间有层次的区别,在多于一个窗口重叠的区域里,只会显示位于顶层的窗口里的内容
当你点击屏幕上一个点的时候,你就选择了处于被点击位置的最顶层窗口,并且这个窗口就会被移到所有窗口的最
顶层,而剩余的窗口的层次顺序不变。
如果你点击的位置不属于任何窗口,则系统会忽略你这次点击。
现在我们希望你写一个程序模拟点击窗口的过程。
输入格式
输入的第一行有两个正整数,即
N
N
N和
M
.
M.
M.
接下来
N
N
N行按照从最下层到最顶层的顺序给出
N
N
N个窗口的位置。
每行包含四个非负整数
x
1
,
y
1
,
x
2
,
y
2
x_1,y_1,x_2,y_2
x1,y1,x2,y2,表示该窗口的一对顶点坐标分别为
(
x
1
,
y
1
)
(x_1,y_1)
(x1,y1)和
(
x
2
,
y
2
)
(x_2,y_2)
(x2,y2)。保证
x
1
<
x
2
,
y
1
<
y
2
x_1<x_2,y_1<y_2
x1<x2,y1<y2.
接下来
M
M
M行每行包含两个非负整数
x
,
y
x,y
x,y,表示一次鼠标点击的坐标。
题目中涉及到的所有点和矩形的顶点的
x
,
y
x,y
x,y坐标分别不超过2559和 1439。
输出格式
输出包括
M
M
M行,每一行表示一次鼠标点击的结果。
如果该次鼠标点击选择了一个窗口,则输出这个窗口的编号(窗口按照输入中的顺序从 1 编号到
N
)
N)
N)。
如果没有,则输出 IGNORED 。
数据范围
1 ≤ N , M ≤ 10 1\leq N,M\leq10 1≤N,M≤10
输入样例:
3 4
0 0 4 4
1 1 5 5
2 2 6 6
1 1
0 0
4 4
0 5
输出样例:
2 1 \begin{array}{cc}2\\1\end{array} 21
1
IGNORED
样例解释
第一次点击的位置同时属于第1和第 2 个窗口,但是由于第 2 个窗口在上面,它被选择并且被置于顶层
第二次点击的位置只属于第1个窗口,因此该次点击选择了此窗口并将其置于顶层。现在的三个窗口的层次关系与
初始状态恰好相反了。
第三次点击的位置同时属于三个窗口的范围,但是由于现在第 1 个窗口处于顶层,它被选择。
最后点击的(0,5)不属于任何窗口。
#include <bits/stdc++.h>
using namespace std;
const int N = 15;
int n, m;
struct Window
{
int x1, y1, x2, y2, id;
}w[N];
int get(int x, int y)
{
for(int i = n; i; i --)
if(x >= w[i].x1 && y >= w[i].y1 && x <= w[i].x2 && y <= w[i].y2)
return i;
return 0;
}
int main()
{
cin >> n >> m;
for(int i = 1; i <= n; i ++)
{
int x1, y1, x2, y2;
cin >> x1 >> y1 >> x2 >> y2;
w[i] = {x1, y1, x2, y2, i};
}
while(m --)
{
int x, y;
cin >> x >> y;
int t = get(x, y);
if(!t)
puts("IGNORED");
else
{
cout << w[t].id << endl;
auto r = w[t];
for(int i = t; i < n; i ++)
w[i] = w[i + 1];//冒泡
w[n] = r;
}
}
return 0;
}
第二次CCF计算机软件能力认证
3202. 相邻数对
给定 n个不同的整数,问这些数中有多少对整数,它们的值正好相差 1。
输出格式
输入的第一行包含一个整数 n,表示给定整数的个数。
第二行包含所给定的 n 个整数。
输出格式
输出一个整数,表示值正好相差 1 的数对的个数。
数据范围
1≤n≤1000
给定的整数为不超过 10000 的非负整数。
输入样例:
6
10 2 6 3 7 8
输出样例:
3
样例解释
值正好相差 11 的数对包括 (2,3),(6,7),(7,8)(2,3),(6,7),(7,8)。
#include <bits/stdc++.h>
using namespace std;
const int N = 1010;
int a[N];
int n;
int ans;
int main()
{
cin >> n;
for(int i = 1; i <= n; i ++)
cin >> a[i];
sort(a + 1, a + 1 + n);
for(int i = 1; i < n; i ++)
if(a[i] + 1 == a[i + 1])
ans ++;
cout << ans << endl;
return 0;
}
3203. 画图
在一个定义了直角坐标系的纸上,画一个 (x1,y1) 到 (x2,y2) 的矩形指将横坐标范围从 x1 到 x2,纵坐标范围从 y1 到 y2 之间的区域涂上颜色。
下图给出了一个画了两个矩形的例子。
第一个矩形是 (1,1) 到 (4,4),用绿色和紫色表示。
第二个矩形是 (2,3) 到 (6,5),用蓝色和紫色表示。
图中,一共有 15 个单位的面积被涂上颜色,其中紫色部分被涂了两次,但在计算面积时只计算一次。
在实际的涂色过程中,所有的矩形都涂成统一的颜色,图中显示不同颜色仅为说明方便。
给出所有要画的矩形,请问总共有多少个单位的面积被涂上颜色。
输入格式
输入的第一行包含一个整数 n,表示要画的矩形的个数。
接下来 n 行,每行 4 个非负整数,分别表示要画的矩形的左下角的横坐标与纵坐标,以及右上角的横坐标与纵坐标。
输出格式
输出一个整数,表示有多少个单位的面积被涂上颜色。
数据范围
1≤n≤100 0≤ 横坐标、纵坐标 ≤100
输入样例:
2
1 1 4 4
2 3 6 5
输出样例:
15
#include <bits/stdc++.h>
using namespace std;
const int N = 110;
bool st[N][N];
int g[N][N];
int n;
int ans;
int main()
{
cin >> n;
while (n -- )
{
int x1, y1, x2, y2;
cin >> x1 >> y1 >> x2 >> y2;
for(int i = x1; i <= x2; i ++)
for(int j = y1; j <= y2; j ++)
st[i][j] = 1;
}
for(int i = 0; i <= 100; i ++)
for(int j = 0; j <= 100; j ++)
ans += st[i][j];
cout << ans << endl;
return 0;
}
3204. 字符串匹配
给出一个字符串和多行文字,在这些文字中找到字符串出现的那些行。
你的程序还需支持大小写敏感选项:当选项打开时,表示同一个字母的大写和小写看作不同的字符;当选项关闭时,表示同一个字母的大写和小写看作相同的字符。
输入格式
输入的第一行包含一个字符串 S𝑆,由大小写英文字母组成。
第二行包含一个数字,表示大小写敏感的选项,当数字为 00 时表示大小写不敏感,当数字为 11 时表示大小写敏感。
第三行包含一个整数 n𝑛,表示给出的文字的行数。
接下来 n𝑛 行,每行包含一个字符串,字符串由大小写英文字母组成,不含空格和其他字符。
输出格式
输出多行,每行包含一个字符串,按出现的顺序依次给出那些包含了字符串 S𝑆 的行。
数据范围
1≤n≤1001≤𝑛≤100,
每个字符串的长度不超过 100100。
输入样例:****
Hello
1
5
HelloWorld
HiHiHelloHiHi
GrepIsAGreatTool
HELLO
HELLOisNOTHello
输出样例:
HelloWorld
HiHiHelloHiHi
HELLOisNOTHello
样例解释
在上面的样例中,第四个字符串虽然也是 Hello
,但是大小写不正确。
如果将输入的第二行改为 00,则第四个字符串应该输出。
#include <bits/stdc++.h>
using namespace std;
string s;
int st;
int n;
void change(string &s)
{
for(int i = 0; i < s.size(); i ++)
s[i] = tolower(s[i]);
return;
}
int main()
{
cin >> s;
cin >> st;
cin >> n;
while(n --)
{
string x;
cin >> x;
// cout << x << endl;
string res = x;
if(st == 0)
{
change(x);
change(s);
}
if(x.find(s) != -1)
cout << res << endl;
}
return 0;
}
第三次CCF计算机软件能力认证
3207. 门禁系统
涛涛最近要负责图书馆的管理工作,需要记录下每天读者的到访情况。
每位读者有一个唯一编号,每条记录用读者的编号来表示。
给出读者的来访记录,请问每一条记录中的读者是第几次出现。
输入格式
输入的第一行包含一个整数 𝑛,表示涛涛的记录条数。
第二行包含 n 个整数,依次表示涛涛的记录中每位读者的编号。
输出格式
输出一行,包含 n个整数,由空格分隔,依次表示每条记录中的读者编号是第几次出现。
数据范围
1≤n≤1000
读者的编号为不超过 n 的正整数。
输入样例:****
5
1 2 1 1 3
输出样例:****
1 1 2 3 1
#include <bits/stdc++.h>
using namespace std;
const int N = 1010;
map<int, int> mp;
int n;
int main()
{
cin >> n;
for(int i = 1; i <= n; i ++)
{
int x;
cin >> x;
mp[x] ++;
cout << mp[x] << " \n"[i == n];
}
return 0;
}