NKOJ考试2305-ny4月底欢乐赛 总结+题解+分析


考试概览

题号名称
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 1s109

思路及代码

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 i1堆和第 i + 1 i+1 i+1堆就会相邻。

果果想知道该怎么拿,才能使得到的价值最多。

输入格式

第一行一个整数 n n n 1 ≤ n ≤ 2 × 1 0 5 1 \le n \le 2 \times 10^5 1n2×105
第二行 n n n个整数 a [ i ] a[i] a[i] 0 ≤ a [ i ] ≤ 1 0 9 0 \le a[i] \le 10^9 0a[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 1N,第 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 2N105
1 ≤ X ≤ 1 0 9 1 \le X \le 10^9 1X109
对于所有的 i ( 1 ≤ i ≤ N − 1 ) , X i < X i + 1 i(1 \le i \le N-1),X_i < X_{i+1} i(1iN1),Xi<Xi+1
1 ≤ A ≤ 1 0 9 1 \le A \le 10^9 1A109
1 ≤ B ≤ 1 0 9 1 \le B \le 10^9 1B109

输出格式

输出一个最少你需要使用的疲劳值。

样例

样例输入 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),(x1,y),(x,y+1),(x,y1)四个位置中的任意一个。小球必须一直处于滚动状态,不可停留。

游戏开始时(第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 1N105
0 ≤ X i ≤ 1 0 5 0 \le X_i \le 10^5 0Xi105
0 ≤ Y i ≤ 1 0 5 0 \le Y_i \le 10^5 0Yi105
1 ≤ T i ≤ 1 0 5 1 \le T_i \le 10^5 1Ti105
T i < T i + 1 ( 1 ≤ i ≤ N − 1 ) T_i < T_{i+1} (1 \le i \le N-1) Ti<Ti+1(1iN1)
所有输入都是整数

思路及代码

注意:这道题要求在同一场游戏中经过给出的所有目标点。
先算出一共要走多少格(纵轴差的绝对值+横轴差的绝对值),如果时间不足,判断为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 xy x + y x+y x+y
情况二
我们用px储存 x + y x+y x+y,用qx储存 x − y x-y xy
接着,我们实时更新px_maxpx_minqx_maxqx_min
得出木框对角线d1px_max-px_mind2qx_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;
}

又到了说再见的时候了,记得三连哦!

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值