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.
10
观察这两个数字从前到后第一个不相同的数字,由于9>1,因此9>10。
用同样的方法,我们可以很容易地证明1919>114514:
1919..
114514
或者是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;
}