考试概览
题号 | 名称 |
---|---|
A | 数字三角 |
B | 跳跃小游戏 |
C | 石子合并 |
D | 最小疲劳值 |
E | 轨迹游戏 |
F | 框蚂蚁 |
项目 | 内容 |
---|---|
说明 | 开心一练 |
类别 | 日常作业题目列表 |
考试规则 | 信息学奥赛规则 |
开始时间 | 2023/4/27 18:30:00 |
结束时间 | 2023/4/27 20:30:00 |
总时长 | 2小时 |
参考人数 | 共 65 人进入, 59 人提交 |
提交限制 | 每题不超过 100 次 |
总结+吐槽
这次考试老师终于仁慈了一回
题目有点水,F肯定不会
总得来说考的还行
A题:好简单。
B题:刚开始读题脑子里全是跳来跳去的兔子,想出思路了就很简单。
C题:刚开始读题脑子里全是一堆一堆的石子,想出思路了就很简单。
D题:被坑了,竟然要开long long int
,气死了。
E题:刚开始读题脑子里全是滚来滚去的球,想骗分,后来想出思路了就很简单。
F题:不出意外的不会,骗了10分,考试结束后思考了很久才想出来。
题解
A题:数字三角
题目描述
有一天,无聊的 zlx 从 1 开始数数,同时在纸上写下每个数的个位数字。因 为她非常热爱直角三角形,所以在纸上写下的数字按照直角三角形排列。现在告 诉你写她了 N 行数字,要求你打出这些数字。
输入格式
一行一个数 N,表示 zlx 已经写了 N 行数字。
输出格式
输出 N 行,第 i 行有 i 个数字,表示 zlx 写下的数字三角形。
样例
样例输入
5
样例输出
1
23
456
7890
12345
提示
对于 100%的数据满足:1 ≤ N ≤ 100。
思路及代码
用num
变量储存个位数,满10变为0。
注意个位数刚开始为1。
#include<bits/stdc++.h>
using namespace std;
int main ()
{
int n,num = 1;
scanf("%d",&n);
for(int i = 1; i <= n; i++){
for(int j = 1; j <= i; j++){
printf("%d",num);
if(num == 9){
num = 0;
}else{
num++;
}
}
printf("\n");
}
return 0;
}
B题:跳跃小游戏
问题描述
何老板最近喜欢上了一款跳跃小游戏,游戏虽然简单,何老板仍旧乐此不疲。
游戏地图可以看作是数轴。游戏开始时,有只兔子位于坐标0位置。何老板的目标是控制兔子跳到坐标为s的位置。
每一秒,何老板可以让兔子停留在原地不动,也可以操控兔子往左或往右跳动一次,其中第i秒兔子跳动的距离为i。也就是说,若第i-1秒兔子位于x位置,那么在第i秒,它可以跳到x-i或x+i位置,也可以保持在x位置。
通过一个关卡花费的时间越少,玩家的得分就越高。何老板想知道,对于给定的关卡,他最少花多少时间就能过关。
输入格式
一行,一个整数s,表示终点坐标
输出格式
一个整数,表示所需最少时间。
样例
样例输入 1
6
样例输出 1
3
样例说明
时间 位置
1 1
2 3
3 6
样例输入 2
2
样例输出 2
2
样例说明
第1秒停留在0位置
第2秒往右跳2,到达2位置
样例输入 3
11
样例输出 3
5
提示
1 ≤ s ≤ 1 0 9 1 \le s \le 10^9 1≤s≤109
思路及代码
用max
变量储存t
秒最多能跳多远。
然后没了。
#include<bits/stdc++.h>
using namespace std;
int main ()
{
long long int max = 0,s,t = 0;
scanf("%d",&s);
for(t = 1; max < s; t++){
max += t;
}
printf("%d",t-1);
return 0;
}
C题:石子合并
问题描述
果果有 n n n堆石子, 每堆石子有 a [ i ] a[i] a[i] 个, 果果每次可以选择相邻的两堆石子,然后拿走少的那一堆,得到的价值是两堆石子个数之和, 直到只剩下一堆石子。
如果拿走了第 i i i堆石子, 那么第 i − 1 i-1 i−1堆和第 i + 1 i+1 i+1堆就会相邻。
果果想知道该怎么拿,才能使得到的价值最多。
输入格式
第一行一个整数
n
n
n,
1
≤
n
≤
2
×
1
0
5
1 \le n \le 2 \times 10^5
1≤n≤2×105
第二行
n
n
n个整数
a
[
i
]
a[i]
a[i],
0
≤
a
[
i
]
≤
1
0
9
0 \le a[i] \le 10^9
0≤a[i]≤109
输出格式
输出得到的最大价值
样例
样例输入
5
2 5 3 5 1
样例输出
31
思路及代码
每堆石子都和最多的那一堆一起操作(不用管它离那堆石子多远)。
#include<bits/stdc++.h>
using namespace std;
long long int a[200005];
int main ()
{
long long int ans = 0,max = -1,n;
scanf("%lld",&n);
for(int i = 0; i < n; i++){
scanf("%lld",&a[i]);
if(max < a[i]){
max = a[i];
}
}
for(int i = 0; i < n; i++){
ans = ans+a[i]+max;
}
ans = ans-max-max;
printf("%lld",ans);
return 0;
}
D题:最小疲劳值
问题描述
有 N N N个小镇排列在一个数轴上,编号为 1 ∼ N 1 \sim N 1∼N,第 i i i个小镇在数轴 X i X_i Xi的位置。
初始你在小镇 1 1 1位置,你现在想游历完所有小镇,你有两种方式可以选择:
- 步行:每走过 1 1 1个单位距离,你的疲劳值会增加 A A A
- 传送:可以传送到任意你选择的位置,疲劳值会增加 B B B
现在请你求出可以游历完所有小镇的最少的疲劳值。
输入格式
输出的第一行包括三个正整数
N
,
A
,
B
N,A,B
N,A,B。
第二行包括
N
N
N个正整数
x
i
x_i
xi表示小镇的坐标。
输入的都是整数
2
≤
N
≤
1
0
5
2 \le N \le 10^5
2≤N≤105
1
≤
X
≤
1
0
9
1 \le X \le 10^9
1≤X≤109
对于所有的
i
(
1
≤
i
≤
N
−
1
)
,
X
i
<
X
i
+
1
i(1 \le i \le N-1),X_i < X_{i+1}
i(1≤i≤N−1),Xi<Xi+1
1
≤
A
≤
1
0
9
1 \le A \le 10^9
1≤A≤109
1
≤
B
≤
1
0
9
1 \le B \le 10^9
1≤B≤109
输出格式
输出一个最少你需要使用的疲劳值。
样例
样例输入 1
4 2 5
1 2 5 7
样例输出 1
11
样例输入 2
7 1 100
40 43 45 105 108 115 124
样例输出 2
84
样例输入 3
7 1 2
24 35 40 68 72 99 103
样例输出 3
12
思路及代码
分析每两个村庄间走过去累还是瞬移过去累,
选择不累的那个方法走。
敲黑板:虽然数字最大是
1
0
9
10^9
109,但是有乘法和加法,要开long long int
我就上了这个当
代码
#include<bits/stdc++.h>
using namespace std;
long long int x[100005];
int main ()
{
long long int n,a,b,l;
long long int ans = 0;
scanf("%lld%lld%lld",&n,&a,&b);
scanf("%lld",&x[0]);
for(long long int i = 1; i < n; i++){
scanf("%lld",&x[i]);
l = x[i]-x[i-1];
if(l*a < b){
ans += l*a;
}else{
ans += b;
}
}
printf("%lld",ans);
return 0;
}
E题:轨迹游戏
问题描述
何老板最近喜欢上了一款手机游戏,游戏虽然简单,何老板仍乐此不疲。
游戏地图是一个二维平面坐标系,玩家操控一个小球在地图上行走。游戏中,若某个时刻小球位于坐标 ( x , y ) (x,y) (x,y)位置,下一秒玩家可以控制小球滚到 ( x + 1 , y ) , ( x − 1 , y ) , ( x , y + 1 ) , ( x , y − 1 ) (x+1,y),(x-1,y),(x,y+1),(x,y-1) (x+1,y),(x−1,y),(x,y+1),(x,y−1)四个位置中的任意一个。小球必须一直处于滚动状态,不可停留。
游戏开始时(第0秒),小球位于坐标 ( 0 , 0 ) (0,0) (0,0)位置。游戏给出了N个指定目标点,第i个目标点的形式为 T i T_i Ti, X i X_i Xi, Y i Y_i Yi,表示在第 T i T_i Ti秒时,小球必须出现在( X i X_i Xi, Y i Y_i Yi)位置。
何老板想提前计算出,理论上他能否通过此游戏,能输出Yes,不能输出No
输入格式
第一行,一个整数N
接下来N行,每行三个整数,
T
i
T_i
Ti,
X
i
X_i
Xi,
Y
i
Y_i
Yi表示一个指定目标点
输出格式
一个单词Yes或No
样例
样例输入 1
2
3 1 2
6 1 1
样例输出 1
Yes
样例说明
按下面轨迹滚动小球即可
(0,0), (0,1), (1,1), (1,2), (1,1), (1,0), (1,1)
样例输入 2
1
2 100 100
样例输出 2
No
样例输入 3
2
5 1 1
100 1 1
样例输出 3
No
提示
1
≤
N
≤
1
0
5
1 \le N \le 10^5
1≤N≤105
0
≤
X
i
≤
1
0
5
0 \le X_i \le 10^5
0≤Xi≤105
0
≤
Y
i
≤
1
0
5
0 \le Y_i \le 10^5
0≤Yi≤105
1
≤
T
i
≤
1
0
5
1 \le T_i \le 10^5
1≤Ti≤105
T
i
<
T
i
+
1
(
1
≤
i
≤
N
−
1
)
T_i < T_{i+1} (1 \le i \le N-1)
Ti<Ti+1(1≤i≤N−1)
所有输入都是整数
思路及代码
注意:这道题要求在同一场游戏中经过给出的所有目标点。
先算出一共要走多少格(纵轴差的绝对值+横轴差的绝对值),如果时间不足,判断为No,直接break
;
如果时间刚刚好,直接Yes;
如果时间过多,那就左右左右消耗时间。因此,如果剩下的时间是双数,就Yes,否则就No。
#include<bits/stdc++.h>
using namespace std;
int main ()
{
int n,t,x,y,nx = 0,ny = 0;
bool can;
scanf("%d",&n);
for(int i = 1; i <= n; i++){
scanf("%d%d%d",&t,&x,&y);
int s;
s = abs(nx-x)+abs(ny-y);
if(t < s){
can = 0;
break;
}else{
if(t == s){
can = 1;
}else if(abs(t-s)%2 == 0){
can = 1;
}else{
can = 0;
break;
}
}
}
if(can){
printf("Yes");
}else{
printf("No");
}
return 0;
}
F题:框蚂蚁
问题描述
何老板的书桌上有n 只蚂蚁,他想用一个正方形的木框将这些蚂蚁都框住。
问,该木框的面积最小是多少。
我们可以将何老板的书桌看作坐标平面,将蚂蚁看作平面上的n 个点。现在告诉你每个点的坐标,要求一个面积最小的正方形,将所有蚂蚁都框在里面(在边框上也算在正方形内)。
为减小难度,何老板要求正方形的边框要么平行于坐标轴,要么与坐标轴呈45 度夹角。
输入格式
第一行,一个整数n。
接下来你n 行,每行两个整数x,y(-1,000,000<=x,y<=1,000,000),表示一只蚂蚁的坐标。
输出格式
一行,一个整数,表示所求最小面积。数据保证结果在long long 范围以内。
样例
样例输入 1
4
1 0
1 2
0 1
2 1
样例输出 1
2
样例输入 2
10
-6709 1221
4441 -1533
4467 763
964 -888
-2570 -1094
5703 1903
5451 1103
-1304 1196
3054 -1476
-7503 -243
样例输出 2
117841952
提示
数据范围:
对于30%的数据: 1<=n<=100
对于100%的数据:1<=n<=100,000
思路及代码
这道题有两种情况:
情况1:正方形与坐标轴平行
我们分别找出最上面、最下面、最左面、最右面的蚂蚁,选择 相对方向 最大的 距离差 作为边长。
情况2:正方形与坐标轴呈45度夹角
对于每一个点
(
x
,
y
)
(x,y)
(x,y),我们可以计算出
x
−
y
x-y
x−y和
x
+
y
x+y
x+y;
我们用px
储存
x
+
y
x+y
x+y,用qx
储存
x
−
y
x-y
x−y;
接着,我们实时更新px_max
、px_min
、qx_max
、qx_min
,
得出木框对角线d1
为px_max-px_min
、d2
为qx_max-qx_min
。
选择最长的对角线算面积。
已知对角线
l
l
l,正方形面积为
l
2
2
\frac{l^2}{2}
2l2。
最后比较情况一最优还是情况二最优。
#include<bits/stdc++.h>
using namespace std;
long long int a[4][2] = {-9999999,0,9999999,0,0,-9999999,0,9999999};
int main ()
{
long long int MIN = -9999999999999999,MAX = 9999999999999999;
long long int n,ans1 = 0,ans2 = 0,temp1,temp2,temp3,temp4,d1,d2;
long long int px_max = MIN,qx_max = MIN,px_min = MAX,qx_min = MAX;
scanf("%lld",&n);
for(int i = 0; i < n; i++){
scanf("%lld%lld",&temp1,&temp2);
temp3 = temp1+temp2;
temp4 = temp1-temp2;
if(temp1 > a[0][0]){
a[0][0] = temp1;
a[0][1] = temp2;
}
if(temp2 > a[2][1]){
a[2][1] = temp2;
a[2][0] = temp1;
}
if(temp1 < a[1][0]){
a[1][0] = temp1;
a[1][1] = temp2;
}
if(temp2 < a[3][1]){
a[3][1] = temp2;
a[3][0] = temp1;
}
if(temp3 > qx_max){
qx_max = temp3;
}
if(temp3 < qx_min){
qx_min = temp3;
}
if(temp4 > px_max){
px_max = temp4;
}
if(temp4 < px_min){
px_min = temp4;
}
}
if(a[2][1]-a[3][1] > a[0][0]-a[1][0]){
ans1 = (a[2][1]-a[3][1])*(a[2][1]-a[3][1]);
}else{
ans1 = (a[0][0]-a[1][0])*(a[0][0]-a[1][0]);
}
d1 = px_max-px_min;
d2 = qx_max-qx_min;
ans2 = d1 < d2 ? d2 : d1;
ans2 = ans2*ans2/2;
if(ans1 < ans2){
printf("%lld",ans1);
}else{
printf("%lld",ans2);
}
return 0;
}
又到了说再见的时候了,记得三连哦!