2021年ZZUSOFT新生赛(第一场)题解

Posted 行码棋

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2021年ZZUSOFT新生赛(第一场)题解相关的知识,希望对你有一定的参考价值。

2021年ZZUSOFT新生赛(第一场)题解

题目链接

注意:数据类型范围,题目中有很多体现

A

直接输出对应的的ASCII码

'A' + 0 代表'A'
'A' + 1 代表'B'
#include<stdio.h>
#include<math.h>

int main()
{
	for(int i=1;i<=26;i++)
	{
		int x;
		scanf("%d",&x);
		printf("%c",'A'+x-1);
	}
	return 0;
}

B

二进制转化为十进制

  • 方法一:可以将相同的因子2提出来,最后化为下面的式子。
#include<stdio.h>
#include<string.h>
char s[100];

int main()
{
	long long sum = 0;
	scanf("%s",s);
	int len = strlen(s);
	for(int i=0;i<len;i++)
		sum = sum * 2 + s[i]-'0';
	printf("%lld\\n",sum);
} 
  • 方法二:从最低位开始按照二进制的定义转化为十进制
#include<stdio.h>
#include<string.h>
char s[66];
int main()
{
	long long res = 0;
	scanf("%s",s);
	int len = strlen(s);
	long long x = 1;
	for(int i=len-1;i>=0;i--,x *= 2)
		res += (s[i]=='1') * x;
	printf("%lld\\n",res);
	return 0;
}

C

剪刀石头布,列举所有情况。为简化程序,只取第一个字母进行比较。

#include<stdio.h>
#include<string.h>
char a[10],b[10];

int main()
{
	scanf("%s%s",a,b);
	if((a[0]=='s' && b[0]=='s') ||
	 (a[0]=='r' && b[0]=='r') || (a[0]=='p' && b[0]=='p'))
		printf("D\\n");
	else if((a[0]=='s' && b[0]=='p')||
	(a[0]=='r' && b[0]=='s')||(a[0]=='p'&& b[0]=='r'))
		printf("L\\n");
	else printf("S\\n");
} 

D

特殊情况先单列出来,然后根据斜率公式求斜率k,进而求出b。

#include<stdio.h>
#include<string.h>

int main()
{
	int x1,y1,x2,y2;
	scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
	if(x1 == x2)
	{
		printf("x=%.6lf\\n",x1);
		return 0;
	}
	double k = ((double)y2-y1)/(x2-x1);
	double b = y1-k*x1;
	printf("%.6lf %.6lf\\n",k,b);
	return 0;
} 

E

直接对应输出即可

#include<stdio.h>
#include<string.h>

int main()
{
	int n;
	char s[10];
	scanf("%d%s",&n,s);
	if(s[n-1]=='s') printf("YES\\n");
	else printf("NO\\n");
} 

F

化简式子得 ∣ x + 1 ∣ |x+1| x+1

不能直接计算 x 2 + 2 x + 1 x^2+2x+1 x2+2x+1,会爆数据范围

当x为int型 ,x*x也为int型,如果乘出来的结果大于int的范围,就会溢出

#include<stdio.h>
#include<math.h>
int main()
{
	long long x;
	scanf("%lld",&x);
    //printf("%lld\\n",abs(x+1));
    if(x<-1) printf("%lld\\n",-x-1);
    else printf("%lld\\n",x+1);
	return 0;
 } 

G

一个点从原点走到另一个点,分为两种情况:

  1. 走的半径大于两点之间的距离,只需要两步就可以走到目标点。这两部走的路径刚好是等腰三角形的两腰,而两点连接而成的线段为等腰三角形的底边

  2. 走的半径小于两点之间的距离,记两点之间的距离为dis,半径为r

    d i s = k ∗ r + x dis = k*r + x dis=kr+x ,k为整数,x为某个数,满足 x < r x < r x<r

    如果x为0,结果自然为k

    如果x不为0, 前面的整数倍的半径可以走k-1步。后面的那个x只需要结合前面整数倍半径的最后一步,就能走到终点(和第一种情况一样)

    第二种情况总结下来就是求dis/r的上取整

#include<stdio.h>
#include<math.h>

int main()
{
	int r,x,y;
	scanf("%d%d%d",&r,&x,&y);
	double dis = sqrt((double)x*x+(double)y*y);
	if(r>dis) printf("2\\n");
	else printf("%d\\n",(int)ceil(dis/r)); 
	return 0;
}

H

本题求直角边平行于行列所在的直线的直角三角形。

可以考虑从直角三角形的直角顶点入手。

直角顶点所在行的点可以组成直角三角形的一个点,所在列的点可以组成直角三角形的一个点,当前行可以选择点的数量为当前行的1的点的个数减一,当前列可以选择的点的个数为当前行的1的点的个数减一,故我们只需要统计每行(row[])每列(col[])有多少点即可。

然后循环遍历每个点,如果当前点为1,则对答案加上 ( r o w [ i ] − 1 ) ∗ ( c o l [ j ] − 1 ) (row[i]-1)*(col[j]-1) (row[i]1)(col[j]1),注意要除去本身

#include<stdio.h>

int g[1005][1005];
int row[1005],col[1005];
int n,m;

int main()
{
	long long res = 0;
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
		{
			scanf("%d",&g[i][j]);
			if(g[i][j]==1) 
			{
				row[i] ++;
				col[j] ++;
			 } 
		}
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
		{
			if(g[i][j]==1)
				res += (row[i]-1)*(col[j]-1);
		}
	printf("%lld\\n",res);
	return 0;
 } 

以上是关于2021年ZZUSOFT新生赛(第一场)题解的主要内容,如果未能解决你的问题,请参考以下文章

2018.12.2 中国石油大学第一次新生训练赛题解

2021-2022 北京化工大学程序设计新生赛 - 问题 N: 聪明的蚂蚁 - 题解

四川大学2021SCUACM新生赛决赛大部分题解(差分dp线段树……)

CQ18阶梯赛第一场题解

ICPC第一场网络赛 题解 + 补题

2021年蓝桥杯青少年组省赛题解(C++)