小白第一次写文章,仅以此文,纪念自己进入acm的招新赛
7-1 Win
分数 100
全屏浏览题目切换布局
作者 ACM-CLUB
单位 东北大学秦皇岛分校
为了实现建设世界一流大学和建设世界一流学科的目标,不少大学都用各种方式提升排名:发表论文、 申请基金、提升多样性. . . 不过看起来这些并不容易,而且 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()
{
string s;
cin>>s;
if(s=="NEU") cout<<"Win"<<endl;
else if(s=="THU") cout<<"Lose"<<endl;
else cout<<"?"<<endl;
return 0;
}
7-2 比大小
分数 30
全屏浏览题目切换布局
作者 ACM-CLUB
单位 东北大学秦皇岛分校
知名数学家田所浩二先生证明了:
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
思路:
用字符串比较的方式直接比较,代码如下
#include<iostream>
#include<string>
using namespace std;
int main()
{
int T;
cin>>T;
for(int i=1;i<=T;i++)
{
string s1,s2;
cin>>s1>>s2;
if(s1==s2) cout<<"="<<endl;
else if(s1<s2) cout<<"<"<<endl;
else cout<<">"<<endl;
}
return 0;
}
7-3 矩阵乘法
分数 70
全屏浏览题目切换布局
作者 ACM-CLUB
单位 东北大学秦皇岛分校
Alice在学线性代数。她觉得线代的计算特别麻烦,于是就来找你,希望你可以给她写一个程序计算两个矩阵的乘积。
矩阵乘法介绍: 矩阵A是一个N行P列的矩阵。 矩阵B是一个K行M列的矩阵。 当P=K时,A和B可以相乘(仅限于AB, BA不一定可行) 假设矩阵C=AB,那么C**i,j=∑t=1P(或K)A**i,t∗B**t,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<iostream>
using namespace std;
int main()
{
int n,p,m;
cin>>n>>p>>m;
int a[110][110]={};
int b[110][110]={};
int c[110][110]={};
for(int i=1;i<=n;i++)
{
for(int j=1;j<=p;j++)
{
cin>>a[i][j];
}
}
for(int i=1;i<=p;i++)
{
for(int j=1;j<=m;j++)
{
cin>>b[i][j];
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
for(int z=1;z<=p;z++)
{
c[i][j]+=a[i][z]*b[z][j];
}
cout<<c[i][j];
cout<<" ";
}
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
思路:
按照正常的思路来说,首先要区分闰年,还要写个数组表示月份,然后算出当前的时间和已知的时间之间的差,再通过约瑟夫环的思想来求出当前的日期(我考试的时候就是这么写,然后耗费了大量时间🤦♂️)
那么我们还有其他办法吗???
有,当然有!!!
请看以下(看完惊到我)知识
利用基姆拉尔森计算公式计算某年某月某日是星期几
(其中基姆拉尔森计算公式:W= (d+2m+3(m+1)/5+y+y/4-y/100+y/400+1)%7
在公式中d表示日期中的日数,m表示月份数,y表示年数。
注意:(1)在公式中要把一月和二月看成是上一年的十三月和十四月,例:如果是2004-1-10则换算成:2003-13-10来代入公式计算; (2)w=0表示周日。)
利用这个知识,我们就可以写出一下代码。(这道题可以写100行,也可以只写10行😭)
#include<iostream>
using namespace std;
int main()
{
int d,m,y,W;
cin>>m>>d>>y;
if(m==1)
{
y--;
m=13;
}
else if(m==2)
{
y--;
m=14;
}
W= (d+2*m+3*(m+1)/5+y+y/4-y/100+y/400+1)%7;
cout<<W<<endl;
return 0;
}
7-5 排列
分数 100
全屏浏览题目切换布局
作者 ACM-CLUB
单位 东北大学秦皇岛分校
给你一个长度为n的排列p1,p2,p3,...,p**n(1≤p**i≤n,且对于任意i\=j,都有p**i\=p**j)
再给你一个整数k,每次操作的定义如下:
选定一个下标j(1≤j≤n−k+1),记m=max{p**j,p**j+1,...,p**j+k−1},然后令p**j,p**j+1,...,p**j+k−1的值都等于m。
你需要使用最少的操作次数,使得p中所有元素的值都等于n。
输入格式:
第一行两个整数n,k (2≤n≤106,2≤k≤n)
接下来一行n个整数,用空格隔开,分别表示p1,p2,...,p**n
输出格式:
一行一个整数,表示最小的操作次数。
输入样例:
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
思路:
每次的操作最多使k-1个数变为n,设这种操作为f1,因此当f1的数量尽可能的多的时候,我们就可以得到我们的答案。
考虑这样一个策略:假设在n所在的位置经过若干次操作(不一定全为f1),然后左右两边经过若干次f1后,刚好满足题意。
在计算操作的次数的时候,可以考虑从两边的f1操作的开始,每次操作减去k-1个数,往中间挤,最后把两一边操作后剩余的数字加起来,然后再经过一次或者两次操作,就可以实现题意。
代码实现如下
#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;
int main()
{
int n,k;
cin>>n>>k;
int p[2000010]={};
int t=0;
for(int i=1;i<=n;i++)
{
cin>>p[i];
if(p[i]==n)
{
t=i;
}
}
cout<<(t-1)/(k-1)+
(n-t)/(k-1)+
ceil(1.0*(n-1-(t-1)/(k-1)*(k-1)-(n-t)/(k-1)*(k-1))/(k-1))<<endl;
return 0;
}
7-6 小步点
分数 100
全屏浏览题目切换布局
作者 ACM-CLUB
单位 东北大学秦皇岛分校
现在是跑步时间。
咖波需要依次经过地图上的五个点位才能完成任务,为了节省体力,他希望以最短的距离跑完这五个点位。
现在给出这五个点位的坐标,你需要帮咖波求出最短距离。(咖波可以从任意一个坐标开始跑步)
输入格式:
总共五行
第i行有两个整数x**i,y**i(−103≤x**i,y**i≤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
思路:
这道题可以用5的排列来枚举先后顺序,然后贪心直接求出答案
代码如下
#include<iostream>
#include<algorithm>
#include<cmath>
#include<iomanip>
using namespace std;
struct lo
{
int x,y;
};
double dis(lo l1,lo l2)
{
return sqrt((l1.x-l2.x)*(l1.x-l2.x)+(l1.y-l2.y)*(l1.y-l2.y));
}
int main()
{
int n=5;
int a[100010]={};
for(int i=1;i<=n;i++)
{
a[i]=i;
}
lo Loc[100010]={};
for(int i=1;i<=n;i++)
{
cin>>Loc[i].x>>Loc[i].y;
}
double Min=0x3f3f3f3f;
while(next_permutation(a+1,a+n+1))
{
double sum=0;
for(int i=1;i<n;i++)
{
sum+=dis(Loc[a[i]],Loc[a[i+1]]);
}
if(sum<Min)
{
Min=sum;
}
}
cout<<fixed<<setprecision(3)<<Min<<endl;
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
思路:
我在考试时,模拟一个一个填空,emmmm,结果显而易见,超时了,所以我们要另辟蹊径😂
每个相邻的P之间所形成的一个区间可以单独处理,这样就把大问题化成了小问题。
对于每个单独的区间的长度,都可能有两种情况,一个是偶数,一个是奇数。长度为偶数的区间,男生和女生能够放的数量是一样的,而长度为奇数的区间,就会多一个位置,既可以给男生,又可以给女生,而最终我们想要的情况要视给定的男生和女生的数量而定,因此我们把这种灵活的位置的数量记录下来,然后在贪心算法的基础下,先把这灵活的位置全部给男生,然后再通过枚举,把位置逐一给女生,直到这种灵活的位置全部给女生。枚举完后我们就得到了我们的答案。
代码如下:
#include<iostream>
#include<string>
using namespace std;
int main()
{
int n,a,b;
cin>>n>>a>>b;
string s;
cin>>s;
s+='P';
int len=0;
int var=0;
int sum=0;
for(int i=1;i<=s.size();i++)
{
if(s[i-1]=='P')
{
if(len%2==1) var++,len--;
sum+=len;
len=0;
}
else
{
len++;
}
}
int Max=min(a,sum/2+var)+min(b,sum/2);
for(int i=1;i<=var;i++)
{
Max=max(Max,min(a,sum/2+var-i)+min(b,sum/2+i));
}
cout<<Max<<endl;
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
思路:
(这道题目最难的貌似是读懂题目)
我们从连续入手,通过变化一个连续的句子的最左边的单词的位置和最右边的单词的位置,来枚举,可能实现当前句子里面包含26个字母的漏字文。右边界用于枚举,使得当前句子的长度尽可能的大,左区间用于缩小,使得句子的字母种类数尽可能不等于26。
(这个东东看起来有点像毛毛虫)
代码实现如下:
#include<iostream>
#include<string>
using namespace std;
const int maxn=1e5+5;
string s[maxn];
int sum[205];
int cnt,ans;
void modify(string s1,int x)
{
for(int i=1;i<=s1.size();i++)
{
if(sum[int (s1[i-1])]==0 && x>0) cnt++;
sum[int (s1[i-1])]+=x;//这行代码只能放在这里,这里考虑到一个顺序问题
if(sum[int (s1[i-1])]==0 && x<0) cnt--;
}
}
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>s[i];
}
int l=1,r=0;
int now=0;
while(r<n)
{
r++;
now+=s[r].size();
modify(s[r],1);
while(cnt==26) modify(s[l],-1),now-=s[l].size(),l++;
ans=max(ans,now);
}
cout<<ans<<endl;
return 0;
}
小结:
- 第四题神奇的星期几公式,嘎嘎
- 在考第六题的时,next_permutation(a+1,a+n+1)不会拼😭,因此,平时函数要尽量自己打
- 第七题把一个大的区间分成了好几个小的区间,有点分治的思想。(告诉我们暴力枚举永远放在最后考虑🤦♂️)
- 第八题用到了字符串长度的伸缩,,通过枚举左右边界来实现连续的句子的枚举。同时,这里封装了一个操作函数,第二参数用于判断操作的种类,通过这样一个方式,让代码显得很简洁