NEUQ-ACM第一周作业(招新题前六题)

1、Win

为了实现建设世界一流大学和建设世界一流学科的目标,不少大学都用各种方式提升排名:发表论文、 申请基金、提升多样性. . . 不过看起来这些并不容易,而且 US News 和 Times 这样的机构并不一定会 公正评判你的工作。因此,一些大学更聪明——自己发布排行榜,这可以使得自己的名次间接变好。比如,通过上海某大学发布的软科排名(ARWU)作为桥梁,咖波甚至可以论证他的小汤河职业技术学院要好于清华大学。

现在,给定三个大写字母,你需要判断:

如果这三个大写字母分别为:NEU,则输出:Win

如果这三个大写字母分别为:THU,则输出:Lose

否则输出:?

输入格式:

一行三个大写字母,如题意所示

输出格式:

一行一个字符串,如题意所示

输入样例1:

NEU

输出样例1:

Win

输入样例2:

THU

输出样例2:

Lose

输入样例3:

KFC

输出样例3:

?

题解: 

#include<bits/stdc++.h>
using namespace std;
int main()
{
	string a;
	cin>>a;
	
	if(a=="NEU")cout<<"Win";
	else if(a=="THU")cout<<"Lose";
	else cout<<"?";
	return 0;
}


2、比大小

知名数学家田所浩二先生证明了:

9>10

证明:写下两个数的十进制表示:

9​.

1​0

观察这两个数字从前到后第一个不相同的数字,由于9>1,因此9>10。

用同样的方法,我们可以很容易地证明1919>114514:

19​19..

11​4514

或者是999>99:

99.​

999​

现在,请你给田所浩二先生写一个程序,用来比较两个输入的数字。

输入格式:

第一行一个整数T(1≤T≤106) ,表示有T组数据

接下来T行,每行两个整数a,b(1≤a,b≤109)

输出格式:

输出总共T行,对于第i行:

如果"a>b",则输出:>

如果"a=b",则输出:=

如果"a<b",则输出:<

输入样例:

5
9 10
114514 1919
999 99
131 131
1314 520

输出样例:

>
<
>
=
<

提示:

为避免输出超时,请使用cout << "\n"替代cout << endl

题解:

原理:两个字符串比大小时,两个字符串自左向右逐个字符相比(按ASCII值大小相比较),直到出现不同的字符或遇’\0’为止。当两个数的位数一样,则直接可以应用字符串的比较。

#include<bits/stdc++.h>
using namespace std;
int main()
{
	int t;
	cin>>t;
	
	for(int i=0;i<t;i++)
	{
		string a,b;                //定义a,b两个字符串
		cin>>a>>b;
		if(a>b)cout<<">";          //直接比大小
		else if(a==b)cout<<"=";
		else if(a<b)cout<<"<";
		cout<<endl;
	}	
	return 0;
}

3、矩阵乘法

 题目描述:

Alice在学线性代数。她觉得线代的计算特别麻烦,于是就来找你,希望你可以给她写一个程序计算两个矩阵的乘积。

矩阵乘法介绍:
矩阵A是一个N行P列的矩阵。
矩阵B是一个K行M列的矩阵。
当P=K时,A和B可以相乘(仅限于AB, BA不一定可行)
假设矩阵C=AB,那么Ci,j​=∑t=1P(或K)​Ai,t​∗Bt,j​

举个例子,假设A是一个2×3的矩阵,B是一个3×2的矩阵,最终结果C是一个2×2的矩阵,如下图所示

输入格式:

输入共一行,有三个整数N,P,M(N,P,M≤100)。表示矩阵A是一个N×P的矩阵,矩阵B是一个P×M的矩阵。

接下来N行,每行P个整数,读入矩阵A。

再接下来P行,每行M个整数,读入矩阵B。

数据保证在输入输出数据可以用int类型存储。

输出格式:

输出N行M列的矩阵C。每行最后一个数后面有一个空格。

输入样例:

在这里给出一组输入。例如:

3 3 3
1 3 2
1 0 0
1 2 2
0 0 2
7 5 0
2 1 1

输出样例:

在这里给出相应的输出。例如:

25 17 4 
0 0 2 
18 12 4 

 题解:

此题关键在于理解题目描述,弄清楚矩阵C的行和列与矩阵A与B的关系。

#include<iostream>
using namespace std;
int main()
{
	int n,p,m;
	cin>>n>>p>>m;	
	int a[n][p],b[p][m];        //定义二维数组a,b,分别表示矩阵A,B
	for(int i=0;i<n;i++)
	{
		for(int j=0;j<p;j++)
		{
			cin>>a[i][j];
		}
	}	
	for(int i=0;i<p;i++)
	{
		for(int j=0;j<m;j++)
		{
			cin>>b[i][j];
		}
	}
	for(int i=0;i<n;i++)               //经逻辑推理可知矩阵C为n行m列
	{
		for(int j=0;j<m;j++)
		{
			int s1=0;
			for(int r=0;r<p;r++)
			{
				s1=s1+a[i][r]*b[r][j];  //用s1来表示矩阵C的其中一个元素
			}
			cout<<s1<<' ';
		}
		cout<<endl;
	}
	return 0;
}

4、 疯狂星期四

题目描述:

已知2022年10月11日是星期二

现在给定你一个日期,你需要计算当天是星期几。

输入格式:

一行三个整数M,D,Y,表示所求日期为:M月D日,Y年

1600≤Y≤2400,保证输入日期均为合法日期。

输出格式:

输出一个数字,表示当前是星期几。

如果星期天,则输出0。

输入样例1:

8 17 1926

输出样例1:

2

输入样例2:

2 29 1904

输出样例2:

1

 思路:

本人在求解时分为三种情况(肯定有更优解),即输入的年份Y>2022、Y==2022、Y<2022,(其中Y==2022时又分为两种情况),接下来,在三种情况下分别求出输入的日期与给定日期的相差的天数,再用天数对7取余,最后判断星期几。

#include<iostream>

using namespace std;
int year(int y)         //year函数用来求y年共有365天还是366天
{
	if(y%4==0&&y%100!=0||y%400==0)return 366;
	else return 365;
}

int md(int y,int m,int d)   //md函数用来求从y年的1月1日到m月d日共有多少天
{
	int sum=d;
	for(int i=1;i<m;i++)
	{
		if(i==1||i==3||i==5||i==7||i==8||i==10||i==12)
			sum+=31;
		else if(i==2)sum+=28+year(y)-365;
		else sum+=30;
	}
	return sum;
}

int main()
{
	int m,d,y,num=0,week;
	cin>>m>>d>>y;
	
	if(y>2022)                      //第一种情况
	{
		num=81+md(y,m,d);           //81是从给定日期到2023年1月1日的天数
		for(int i=2023;i<y;i++)     //接下来加上中间完整的年份的天数
		{
			num+=year(i);
		}
		week=num%7+2;
		if(week>=7)week-=7;         //注意星期天用0表示
	}
	else if(y<2022)                 //第二种情况
	{
		num=year(y)-md(y,m,d)+md(2022,10,11);
		for(int i=y+1;i<2022;i++)   //同上,加上中间天数满一年的部分
		{
			num+=year(i);
		}
		week=2-num%7;
		if(week<0)week+=7;
	}
	else if(y==2022)                //第三种情况
	{
		if(md(y,m,d)>md(2022,10,11))      //输入日期大于10月11日时
		{
			num=md(y,m,d)-md(2022,10,11);
			week=num%7+2;
			if(week>=7)week-=7;
		}
		else                              //输入日期小于或等于10月11日时
		{
			num=md(2022,10,11)-md(y,m,d);
			week=2-num%7;
			if(week<0)week+=7;
		}
	}
	cout<<week;
	return 0;
}


 5、排列

题目描述: 

给你一个长度为n的排列p1​,p2​,p3​,...,pn​(1 ≤ pi​ ≤ n,且对于任意i != j,都有pi​ != pj​)

再给你一个整数k,每次操作的定义如下:

选定一个下标j(1 ≤ j ≤ n−k+1),记m = max {pj​ , pj+1 ​, ... , pj+k−1​ },然后令pj ​, pj+1 ​, ... , pj+k−1​的值都等于m。

你需要使用最少的操作次数,使得p中所有元素的值都等于n。

输入格式:

第一行两个整数n,k (2 ≤ n ≤ 106 , 2 ≤ k ≤ n )

接下来一行n个整数,用空格隔开,分别表示p1​ , p2​, ... , pn​

输出格式:

一行一个整数,表示最小的操作次数。

输入样例:

6 3
1 6 4 2 3 5

输出样例:

3

样例解释:

第一次操作选择:j=1,操作后p为:6 6 6 2 3 5

第二次操作选择:j=3,操作后p为:6 6 6 6 6 5

第三次操作选择:j=4,操作后p为:6 6 6 6 6 6

题解: 

本人的思路应该绕了点,而且有一些可以改进的地方,还请各位大佬指正。

#include<iostream>

using namespace std;
int main()
{
	int n,k,r,js=0,i,min=0;     //js表示操作次数
	cin>>n>>k;
	int a[n];
	for(i=0;i<n;i++)
	{
		cin>>a[i];          //用数组a来储存这一行数
	}
    
	for(r=0;r<n;r++)
	{
		if(a[r]==n)break;    //求出其中最大值的数组下标
	}

	if(n<=k)js=1;            //第一种情况
	else if(k==2)js=n-1;     //第二种情况
	else                     //第三种情况:其中又分为两种情况。
	{
		if(r+1<=k||n-r<=k)    /*当最大值的位置靠近这行数的两侧,即可进行第一
                              此操作把最大值所在那一侧的k个数都同化时*/
		{
			js++;
			n-=k;
			while(n-k+1>0)
			{
				n=n-k+1;
				js++;
			}
			js++;
		}
		else                    //当最大值的位置位于中间位置时
		{						
			for(i=0;i<k;i++)    /*此时一开始是同化最大值右边的k-1位数,还是k-2位
                                亦或是k-3位呢?没关系,直接枚举,取最小的操作次数*/
            {
				int r3=r,js2=0;   //js2表示操作次数
				r3+=k-i-1;
				js2++;
				while(r3+k-1<n-1) //向右同化
				{
					js2++;
					r3+=k-1;
				}
				js2++;
				int r4=r-i;
				while(r4-(k-1)>0) //向左同化
				{
					js2++;
					r4-=k-1;
				}
				js2++;
				if(i==1)min=js2;
				else if(js2<min)min=js2;
			}
		}
	}
	if(js==0)cout<<min;   //判断程序进入了哪个if分支
	else cout<<js;
	return 0;
}

6、小步点 

题目描述: 

现在是跑步时间。

咖波需要依次经过地图上的五个点位才能完成任务,为了节省体力,他希望以最短的距离跑完这五个点位。

现在给出这五个点位的坐标,你需要帮咖波求出最短距离。(咖波可以从任意一个坐标开始跑步)

输入格式:

总共五行

第i行有两个整数xi​,yi​(−103≤xi​,yi​≤103),表示第i个点位的坐标值。

数据保证不存在坐标相同的点。

输出格式:

输出一个实数,表示最短的跑步距离(保留三位小数)

输入样例:

0 0
0 2
2 2
2 0
1 1

输出样例:

6.828

样例解释:

可选择从(0,0)点开始,依次经过(0,2),(1,1),(2,0),(2,2)

此时距离为:2+2​+2​+2=6.828,可以证明这是最短的路径。

题解:

题目描述比较简单,可以直接枚举取最短路径。

#include<iostream>
#include<math.h>

using namespace std;
double h(int a1,int a2,int b1,int b2)        //定义h函数求点(a1,a2)与点(b1,b2)的距离
{
	return sqrt(pow(a1-b1,2)+pow(a2-b2,2));
}

int main()
{
	int x[5][2],i,j;
	for(i=0;i<5;i++)
		for(j=0;j<2;j++)
			cin>>x[i][j];                    //用二维数组储存五个坐标
	
	double sum,min;
	int a,b,c,d,e,sign=0;
	
	for(a=0;a<5;a++)
	{
		double s1,s2,s3,s4;
		for(b=0;b<5;b++)
		{
			while(b==a)b++;
			s1=h(x[a][0],x[a][1],x[b][0],x[b][1]);
			for(c=0;c<5;c++)
			{
				while(c==b||c==a)c++;
				s2=h(x[b][0],x[b][1],x[c][0],x[c][1])+s1;
				for(d=0;d<5;d++)
				{
					while(d==a||d==b||d==c)d++;
					s3=h(x[c][0],x[c][1],x[d][0],x[d][1])+s2;				
					for(e=0;e<5;e++)
					{
						while(e==a||e==b||e==c||e==d)e++;
						s4=h(x[d][0],x[d][1],x[e][0],x[e][1])+s3;				
						if(sign==0)min=s4;						
						else if(s4<min)min=s4;        //sign用于让求得的第一个距离为min                                                                       						    
                        sign=1;
					}
				}
			}				
		}
	}
	printf("%.3lf",min);	
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值