7-1 Win
分数 100
为了实现建设世界一流大学和建设世界一流学科的目标,不少大学都用各种方式提升排名:发表论文、 申请基金、提升多样性. . . 不过看起来这些并不容易,而且 US News 和 Times 这样的机构并不一定会 公正评判你的工作。因此,一些大学更聪明——自己发布排行榜,这可以使得自己的名次间接变好。比如,通过上海某大学发布的软科排名(ARWU)作为桥梁,咖波甚至可以论证他的小汤河职业技术学院要好于清华大学:
现在,给定三个大写字母,你需要判断:
如果这三个大写字母分别为:NEU,则输出:Win
如果这三个大写字母分别为:THU,则输出:Lose
否则输出:?
输入格式:
一行三个大写字母,如题意所示
输出格式:
一行一个字符串,如题意所示
输入样例1:
NEU
输出样例1:
Win
输入样例2:
THU
输出样例2:
Lose
输入样例3:
KFC
输出样例3:
?
代码长度限制
16 KB
时间限制
1000 ms
内存限制
128 MB
分析:简单的分支结构即可
#include<iostream>
using namespace std;
int main()
{
char a[3];
cin>>a[0]>>a[1]>>a[2];
if(a[0]=='N'&&a[1]=='E'&&a[2]=='U')
{
cout<<"Win";
}
else if(a[0]=='T'&&a[1]=='H'&&a[2]=='U')
{
cout<<"Lose";
}
else
{
cout<<"?";
}
return 0;
}
7-2 比大小
分数 30
知名数学家田所浩二先生证明了:
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
代码长度限制
16 KB
时间限制
2000 ms
内存限制
128 MB
分析:根据题目要求,“比较”两个数大小的方式为:先从左往右找到第一个不相等的数,该数字的大小关系即为两个数的大小关系。为了便于比较每一位数字的大小,我们不妨将数字以字符串的形式存储。
int N;
cin>>N;//N组数据
string a[N],b[N];
for(int i=0;i<N;i++)
{
cin>>a[i]>>b[i];
}
大多数时候参与比较的两个数位数并不相同,我们需要在位数较小的数字后补上“0”, 这样输入部分就完成了。
int N;
cin>>N;
string a[N],b[N];
for(int i=0;i<N;i++)
{
cin>>a[i]>>b[i];
if(a[i].size()>b[i].size())
{
while(a[i].size()>b[i].size())
{
b[i]+='0';
}
}
else if(a[i].size()<b[i].size())
{
while(a[i].size()<b[i].size())
{
a[i]+='0';
}
}
}
接下来进行比较,利用for循环从左到右历遍每一位数字并进行比较,这里使用了变量q进行标记,只有当每一位都相等时q在跳脱循环后仍为true;
for(int i=0;i<N;i++)
{
bool q=1;
for(int j=0;j<a[i].size();j++)//从左到右历遍每一位数
{
q=(a[i][j]==b[i][j])&&q;
if(a[i][j]==b[i][j])
{
continue;//当某一位相等时进行下一轮循环
}
else if(a[i][j]>b[i][j])
{
cout<<">\n";
break;
}
else
{
cout<<"<\n";
break;
}
}
if(q==true)//q仅在所有位相等时为true
{
cout<<"=\n";
}
}
将上述过程拼接起来得到最终答案如下
#include<iostream>
#include<string>
using namespace std;
int main()
{
int N;
cin>>N;
string a[N],b[N];
for(int i=0;i<N;i++)
{
cin>>a[i]>>b[i];
if(a[i].size()>b[i].size())
{
while(a[i].size()>b[i].size())
{
b[i]+='0';
}
}
else if(a[i].size()<b[i].size())
{
while(a[i].size()<b[i].size())
{
a[i]+='0';
}
}
}
for(int i=0;i<N;i++)
{
bool q=1;
for(int j=0;j<a[i].size();j++)
{
q=(a[i][j]==b[i][j])&&q;
if(a[i][j]==b[i][j])
{
continue;
}
else if(a[i][j]>b[i][j])
{
cout<<">\n";
break;
}
else
{
cout<<"<\n";
break;
}
}
if(q==true)
{
cout<<"=\n";
}
}
return 0;
}
7-3 矩阵乘法
分数 70
作者 ACM-CLUB
单位 东北大学秦皇岛分校
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
代码长度限制
16 KB
时间限制
1000 ms
内存限制
64 MB
#include<bits/stdc++.h>
using namespace std;
int main()
{
int N,P,M;//首先输入三个相关参数
cin>>N>>P>>M;
int a[105][105],b[105][105],c[105][105];//用a,b,c三个数组分别存储两个输入的矩阵和运算结果
memset(c,0,sizeof(c));//将数组c的所有元素初始化为0
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<P;i++)
{
for(int j=0;j<N;j++)
{
for(int k=0;k<M;k++)
{
c[j][k]+=a[j][i]*b[i][k];//按要求进行运算并赋值给数组c
}
}
}
for(int i=0;i<N;i++)
{
for(int j=0;j<M;j++)
{
cout<<c[i][j]<<" ";//按次序输出数组c中元素
}
cout<<endl;
}
return 0;
}
7-4 疯狂星期四
分数 200
作者 ACM-CLUB
单位 东北大学秦皇岛分校
已知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
代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB
本题我本人也是尝试了很久,包括但不限于使用各种奇怪的循环、判断,费时费力,后来发现可直接套用蔡勒(Zeller)公式,具体可在站内搜索。
#include<iostream>
using namespace std;
int main()
{
int m,d,y,w;//月份m,日期d,年份y,星期w
cin>>m>>d>>y;
if(m<3)//这里往下直接套用公式
{
m+=12;
y--;
}
int C=y/100,Y=y%100,M=m,D=d;
w=(C/4-2*C+Y+Y/4+13*(M+1)/5+D-1)%7;
w=w>=0?w:7+w;
cout<<w%7;
return 0;
}
7-5 排列
分数 100
作者 ACM-CLUB
单位 东北大学秦皇岛分校
给你一个长度为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
代码长度限制
16 KB
时间限制
1000 ms
内存限制
128 MB
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n,k,x,i,f,l;//x:数值为n的数位于第x个
cin>>n>>k;
for(x=1;1;x++)
{
cin>>i;
if(n==i)
{
break;
}
}
f=(1.0*x)/(1.0*k)>x/k?x/k+1:x/k;
x+=k-x%k;
l=(1.0*(n-x+1))/(1.0*k)>(n-x+1)/k?(n-x+1)/k+1:(n-x+1)/k;
cout<<f+l;
return 0;
}
7-6 小步点
分数 100
全屏浏览题目
切换布局
作者 ACM-CLUB
单位 东北大学秦皇岛分校
现在是跑步时间。
咖波需要依次经过地图上的五个点位才能完成任务,为了节省体力,他希望以最短的距离跑完这五个点位。
现在给出这五个点位的坐标,你需要帮咖波求出最短距离。(咖波可以从任意一个坐标开始跑步)
输入格式:
总共五行
第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,可以证明这是最短的路径。
代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB
#include<iostream>
#include<cmath>
#include<iomanip>
using namespace std;
double le(float x1,float y1,float x2,float y2)//输入两个点的坐标,输出它们间的距离
{
double s=sqrtf((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
return s;
}
int main()
{
float x[5],y[5];
float s=0,min;
for(int i=0;i<5;i++)
{
cin>>x[i]>>y[i];//输入5个点的坐标
}
min=le(x[1],y[1],x[2],y[2])+le(x[2],y[2],x[3],y[3])+le(x[3],y[3],x[4],y[4])+le(x[4],y[4],x[0],y[0]);初始化min
for(int i=0;i<5;i++)
{
for(int j=0;j<5;j++)
{
if(j==i)
{
continue;
}
for(int k=0;k<5;k++)
{
if(k==i||k==j)
{
continue;
}
for(int l=0;l<5;l++)
{
if(l==i||l==j||l==k)
{
continue;
}
for(int m=0;m<5;m++)
{
if(m==i||m==j||m==k||m==l)
{
continue;
}
min=min<(le(x[i],y[i],x[j],y[j])+le(x[j],y[j],x[k],y[k])+le(x[k],y[k],x[l],y[l])+le(x[l],y[l],x[m],y[m]))?min:(le(x[i],y[i],x[j],y[j])+le(x[j],y[j],x[k],y[k])+le(x[k],y[k],x[l],y[l])+le(x[l],y[l],x[m],y[m]));
}
}
}
}
}//枚举法找最小值
cout<<fixed<<setprecision(3)<<min;
return 0;
}
7-7 原神生日会
分数 100
作者 ACM-CLUB
单位 东北大学秦皇岛分校
注:空、荧、派蒙均为游戏原神里的人名。
有a个空(男旅行者)和b个荧(女旅行者)在会场外排队参加原神生日会。不幸的是,会场里只有N个座位,而且已经有若干个派蒙(可以是0个)已经坐在会场里面了。
- 每个男旅行者都希望坐在他边上的是女旅行者或者派蒙。
- 每个女旅行者都希望坐在她边上的是男旅行者或者派蒙。
换句话说,男旅行者不希望和其他男旅行者坐一起,女旅行者不希望和其他女旅行者坐一起。
如果会场内没有符合旅行者心意的位置,那么旅行者会选择不参加原神生日会。
作为活动组织者的你,希望能参加生日会的旅行者尽可能的多,现在给出会场内每个派蒙的位置,请你求出最多有几个旅行者会来参加生日会。
输入格式:
输入共两行。
第一行有三数,分别为N,a,b(1≤n≤2∗105,0≤a,b≤2∗105,a+b>0)。表示会场内有N个位子,会场外有a个男旅行者,有b个女旅行者。
第二行是一个由字符"."和字符"P"组成的字符串。
"."表示空位,"P"表示这个位置被派蒙占了。
输出格式:
输出一个整数,表示最多可以有几个旅行者参加生日会。
输入样例:
在这里给出一组输入。例如:
11 3 10
.P....PP.P.
输出样例:
在这里给出相应的输出。例如:
7
样例解释
我们用P来表示派蒙,A来表示男旅行者,B来表示女旅行者,最终会场内的座位情况是这样的:BPABABPPAPB
代码长度限制
16 KB
时间限制
1000 ms
内存限制
64 MB
#include <bits/stdc++.h>
using namespace std;
char ch[200005];
int N, A, B, len, a, b, c, d, sum, now, ans;
int main() {
cin >> N >> A >> B;
scanf("%s", ch + 1), len = strlen(ch + 1);
for (int i = 1; i <= len; ) {
if (ch[i] == 'P') ++i;
else { // 处理连续的空位
for (now = 0; i <= len && ch[i] == '.'; ++i) ++now;
// now就是当前有多少个连续的空位
c = (now + 1) / 2; // 先把多余的空位(假如有的话)分给男生
d = now - c;
a += c, b += d;
if (c != d) ++sum; // 记录有多少个可以灵活分配的空位
}
}
ans = min(a, A) + min(b, B);
// ans存储最终答案,a是分配给男生的位子数量,A是男生人数,b和B同理
for (int i = 1; i <= sum; ++i) {
--a, ++b; // 一个一个将灵活分配的空位多分给女生
ans = max(ans, min(a, A) + min(b, B));
}
printf("%d\n",ans);
return 0;
}
7-8 漏字文
分数 70
全屏浏览题目
切换布局
作者 ACM-CLUB
单位 东北大学秦皇岛分校
有意避免使用某个或某几个特定字母的写成的文章称漏字文(英语lipogram,希腊语lipagrammatos,意为“失踪的字母”),漏字文可能在写作或文字游戏中出现。公元前5世纪希腊诗人里斐奥多鲁斯(Tryphiodorus)写的24卷史诗中,每一卷都省略希腊字母中的一个不同字母。
现在给你一段仅由空格和小写字母组成的字符串,请你找出其中最长的一段连续的漏字文,并输出漏字文的长度(即该段文字中字母的个数)。
输入格式:
输入共两行。
第一行一个数N(1≤N≤105),表示有N个由小写字母组成的单词。
第二行是一个字符串,有N个长度不超过10的单词,每个单词间用一个空格隔开。
输出格式:
一个整数,表示漏字文的长度。
输入样例:
在这里给出一组输入。例如:
9
the quick brown fox jumps over the lazy dog
输出样例:
在这里给出相应的输出。例如:
32
样例解释
“the quick brown fox jumps over the lazy dog”包含了所有的字母。
其中最长的漏字文是“the quick brown fox jumps over the lazy”,长度是32(即里面有32个字母)。这段文字没有字母d和g,符合漏字文的条件。
代码长度限制
16 KB
时间限制
1000 ms
内存限制
256 MB
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5;
string s[maxn];
int sum[205];
int N, ans, now, cnt;
// now表示当前选择的代词的总长
// cnt表示选中的单词中字母的种类,初始值为0
void modify(string s, int x) { // 添加或删除单词s,x=1为添加,x=-1为删除
int len = s.length();
for (int i = 0; i < len; ++i) {
if (sum[s[i]] == 0 && x > 0) ++cnt; // 新字母,种类加一
sum[s[i]] += x;
if (sum[s[i]] == 0 && x < 0) --cnt; // 删除最后一个该字母,种类减一
}
}
int main() {
int L = 1, R = 0;
cin >> N;
for (int i = 1; i <= N; ++i) cin >> s[i];
while (R < N) {
++R;
modify(s[R], 1); //在后面添加一个单词
now += s[R].length(); //加上这个单词的长度
while (cnt == 26) modify(s[L], -1), now -= s[L].length(), ++L;
// 当选中的文字是全字文的时候删除最前面的单词直到选中的文字是漏字文
ans = max(ans, now); //更新答案
}
cout << ans << endl;
return 0;
}