2024大连东软信息学院 “星巴克杯” 校程序设计竞赛
前言:排名第二,得到奖金300元。罚时太多,最后一题真的不是人干的事情啊,那么多人做出来,一问才知道他们见过。谁能想到那个规律啊!!
四道题全场没有做出来的,但是我感觉我做的正确,嗯,个人感觉。
每道题附带个人源代码以及题解,还有吐槽内容。
2539: Champion Glory
内存限制:128 MB
时间限制:1.000 S
评测方式:文本比较
题目描述
什么???2024年“星巴克杯” N(Neusoft)CPC 居然有奖金,大二(准大三)老登们表示不服,所以希望拿到奖金的小登懂点事(开玩笑)。
本题很简单只需要打印出:“\ Champion I’m here //” (看样例输出)
样例输入 复制
样例输出 复制
\ Champion I’m here //
题解
轻视了,草率了
第一题啊,复制了就上交。\\ 这玩意 你得多敲两个在C语言中,如果你想要输出反斜杠(\)字符,你不能直接在字符串中使用一个单独的\,因为\在C语言字符串中被用作转义字符的起始符号。例如,\n代表换行符,\t代表制表符等。为了输出一个实际的反斜杠字符,你需要使用两个反斜杠(\)来表示一个反斜杠字符。
如果你想要输出\(即两个反斜杠字符),你需要在字符串中使用四个反斜杠(\\),因为每个反斜杠都需要被转义。
#include<bits/stdc++.h>
using namespace std;
int main(){
int i,j,k;
printf("\\\\ Champion I'm here //");
return 0;
}
/**************************************************************
Problem: 2539
User: neuteam133 []
Language: C++
Result: 正确
Time:3 ms
Memory:2176 kb
****************************************************************/
2540: 穿衣选择
此题服务器出错了,所以送了一个分数
#include<bits/stdc++.h>
using namespace std;
int main(){
int i,j,k;
int x;cin>>x;
if(x<10)printf("穿厚外套\n");
if(x>=10&&x<=20)printf("穿夹克\n");
if(x>20)printf("穿T恤\n");
return 0;
}
/**************************************************************
Problem: 2544
User: neuteam133 []
Language: C++
Result: 正确
Time:3 ms
Memory:2176 kb
****************************************************************/
2536: 世界人口日
内存限制:128 MB
时间限制:1.000 S
评测方式:文本比较
题目描述
今天是“世界人口日”,1987年7月11日,南斯拉夫的一个婴儿降生,被联合国象征性地认定为是地球上第50亿个人,并宣布地球人口突破50亿大关。为此小h想写一个数列A来纪念一下,指定了一下的规则,A[1] = 1,A[2] = A[1] + 50,A[3] = A[2] + 50 … A[n] = A[n-1] + 50,求第i项是多少(i≤50)?
输入
输入一个整数i,表示数列A的第i项
输出
输出第i项的值
样例输入 复制
3
样例输出 复制
101
题解
不解释,没任何算法
#include<bits/stdc++.h>
using namespace std;
int main(){
int i,j,k;
int n;
cin>>n;
printf("%d\n",(n-1)*50+1);
return 0;
}
/**************************************************************
Problem: 2536
User: neuteam133 []
Language: C++
Result: 正确
Time:3 ms
Memory:2176 kb
****************************************************************/
2538: 碰撞
内存限制:128 MB
时间限制:2.000 S
评测方式:文本比较
题目描述
有 n 个数,从左到右编号为 1 到 n,这些数有两种颜色:0 和 1。按照从 1 到 n 的编号依次将这些数放入容器 S1 中。
每当有一个数 x 进入到 S1 时,你必须在 S1 中选择一个颜色与 x 不同的数 y,x 和 y 会进行碰撞,从而使 x 和 y 消失,并且将碰撞后的产物 x + y 放入另一个容器 S2 中。如果不存在与 x 颜色不同的数 y,则 x 留在 S1 中。
当所有的数都放入 S1 后,S2 中最小的元素的最大值是多少?
输入
第一行包含一个整数 n (1 <= n <= 1e5) —— 数组的大小
第二行包含 n 个数 a1, a2, a3 … an (1 <= ai <= 1e8) —— 整数序列
第三行包含 n 个数 c1, c2, c3 … cn (0 <= ci <= 1) —— ci 表示第 i 个数的颜色
保证至少有一个ci=0,至少有一个ci=1
输出
输出一个整数,代表 S2 中最小元素的最大值
样例输入 复制
7
3 3 4 4 5 3 1
0 0 1 1 1 0 0
样例输出 复制
7
题解
难度很大,不会做
下面这段是考场写的,其实我感觉没啥错。。。。有可能我题意理解错误
#include<bits/stdc++.h>
using namespace std;
priority_queue <int,vector<int>,greater<int> > q0,q1;
int n,a[100005],c,ans=0x3f3f3f;
int main(){
int i,j,k;
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
cin>>n;
for(i=1;i<=n;i++){
cin>>a[i];
}
for(i=1;i<=n;i++){
cin>>c;
if(c==0){
if(q1.size()){
ans=min(ans,q1.top()+a[i]);
q1.pop();
}
else q0.push(a[i]);
}
else {
if(q0.size()){
ans=min(ans,q0.top()+a[i]);
q0.pop();
}
else q1.push(a[i]);
}
}
cout<<ans<<endl;
return 0;
}
2542: 扶老奶奶过马路
内存限制:128 MB
时间限制:1.000 S
评测方式:文本比较
题目描述
有一群小朋友扶一群老奶奶过马路,但小朋友只记住了扶老奶奶过马路是“做好事”,却忽略了老奶奶是否有过马路的真实需求。 就出现了,把老奶奶扶过去,又扶回来的情况。 假设,有N位老奶奶站在马路东侧,编号1至N,第1分钟,把所有编号能够被1整除的老奶奶扶到马路对面(即所有老奶奶从东侧到西侧,因为所有数被1除,都余0); 第2分钟,把所有编号能够被2整除的老奶奶扶到马路对面(东侧的到西侧,西侧的到东侧,例如2号老奶奶,第1分钟被从东扶到西,第2分钟又被扶着回来); 第3分钟,把所有编号能够被3整除的老奶奶扶到马路对面(东侧的到西侧,西侧的到东侧);……; 第N分钟,把所有能够被N整除编号的老奶奶扶到马路对面(东侧的到西侧,西侧的到东侧); 问:最后,马路东侧有多少老奶奶,即多少老奶奶没有过马路?
输入
输入有两行:
第一行为测试案例的个数M;
第二行是M个整数,每个整数对应一个测试数据的N。(1<=N<=109)
输出
你的输出应该有M行,每行一个整数,表示与输入对应的答案
样例输入 复制
2
1 5
样例输出 复制
0
3
提示
以N=5为例,第1分钟,1、2、3、4、5从东到西;第2分钟,2、4从西到东;第3分钟,3从西到东;第4分钟,4从东到西;第5分钟,5从西到东;最后,2、3、5在东侧,1、4在西侧。
题解
小学五年级奥数题目
很好理解嘛,你想啊,如果一个数有偶数个因数,必定能来回嘛
你不行你打个表,找规律。你看到数据那么大,而且答案固定,没规律不可能出出来
下面是打表程序
#include<bits/stdc++.h>
using namespace std;
int t,n,a[100005];
int main(){
int i,j,k;
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
cin>>t;
for(n=1;n<=100;n++){
memset(a,1,sizeof(a));
for(i=1;i<=n;i++)
{
for(j=i;j<=n;j+=i)
a[j]=!a[j];
}
int ans=0;
for(i=1;i<=n;i++)
ans+=a[i];
printf("%d:%d\n",n,ans);
}
return 0;
}
1:0
2:1
3:2
4:2
5:3
6:4
7:5
8:6
9:6
10:7
11:8
12:9
13:10
14:11
15:12
16:12
17:13
18:14
19:15
20:16
21:17
22:18
23:19
24:20
25:20
26:21
27:22
28:23
29:24
30:25
31:26
32:27
33:28
34:29
35:30
36:30
37:31
38:32
39:33
40:34
41:35
42:36
43:37
44:38
45:39
46:40
47:41
48:42
49:42
50:43
51:44
52:45
53:46
54:47
55:48
56:49
57:50
58:51
59:52
60:53
61:54
62:55
63:56
64:56
65:57
66:58
67:59
68:60
69:61
70:62
71:63
72:64
73:65
74:66
75:67
76:68
77:69
78:70
79:71
80:72
81:72
82:73
83:74
84:75
85:76
86:77
87:78
88:79
89:80
90:81
91:82
92:83
93:84
94:85
95:86
96:87
97:88
98:89
99:90
100:90
看出来了?只有n*n的数字才能不动
下面正解
#include<bits/stdc++.h>
using namespace std;
int t,n,a[100005];
int main(){
int i,j,k;
cin>>t;
while(t--){
cin>>n;
int x=sqrt(n);
cout<<n-x<<endl;
}
return 0;
}
/**************************************************************
Problem: 2542
User: neuteam133 []
Language: C++
Result: 正确
Time:3 ms
Memory:2568 kb
****************************************************************/
2537: 操作集合
内存限制:128 MB
时间限制:0.500 S
评测方式:文本比较
题目描述
有一个大小为 n 的集合定义为 2a1、2a2、…… 2an,你可以对集合进行操作:
约定一次完整的操作过程如下:
第一步:从集合当中取出两个数并且把他们从集合当中删除,约定较小的为 x,较大的为 y,即 x <= y
第二步:将 2x 插入到集合当中
第三步:如果 x != y,则将 y - x 也插入到集合当中
问:经过若干次的操作之后,集合的大小最小可以为多少?
输入
第一行,包含一个整数 n (1 <= n <= 105)
第二行,包含 n 个整数 a1、a2、…… an 是为集合 a
输出
输出一个整数,表示经过若干次操作之后集合大小的最小值
样例输入 复制
5
1 1 1 3 1
样例输出 复制
1
题解
难题,我考场上没搓出来,但是我没有感觉有啥子错误
我当时的想法很简单,要使得集合大小尽可能小嘛,你就要尽量删除数据,但是你看下操作步骤,你能发现出来两个,回去的可能是一个,可以是两个
但是你要求小啊,那你一定要尽量小。
2x相对应的就是x+1对吧,因为集合是2的倍数
然后我们按照样例举例
1有4个 操作两次能减少2个,同时会生成2个2
2有2个了,操作一次,产生1个3
加上原来的3,你还能操作1次
一共操作4次,减少了4.
n-4=1
但是不知道为啥子出错了哈,下面是错误代码
#include<bits/stdc++.h>
using namespace std;
int n,a[10005],maxn;
int main(){
int i,j,k;
cin>>n;
for(i=1;i<=n;i++){
int x;cin>>x;
a[x]++;maxn=max(maxn,x);
}
int ans=n;
for(i=0;i<=maxn;i++)
{
ans-=a[i]/2;
a[i+1]+=a[i]/2;
}
cout<<ans<<endl;
return 0;
}
/**************************************************************
Problem: 2537
User: neuteam133 []
Language: C++
Result: 运行错误
****************************************************************/
2540: 航班调度
内存限制:128 MB
时间限制:1.000 S
评测方式:文本比较
题目描述
这不仅是一次技能的测试,更是一次对自我热爱和坚持的探索。希望,通过这次编程之旅,你能够发现自己对编程的那份独特热爱,并且能够持之以恒地追求卓越。 现在在机场里有n架准备起飞的飞机,每一架准备起飞的飞机都有自己的航班号(number),优先级(priority),现在机场人员需要你来帮他们排一下,飞机的起飞顺序;其中n<1024,number长度不超过10,priority:1-1024(每架飞机优先级不会重复);ps:priority值越高的先起飞。
输入
一共输入n+1行 第一行输入n代表n架飞机 接下来的n行输入格式为number priority
输出
按照排序后的顺序输出飞机航班号
样例输入 复制
3
MH370 10
MU9045 50
CA072 60
样例输出 复制
CA072
MU9045
MH370
题解
排序题,不解释
#include<bits/stdc++.h>
using namespace std;
int n;
struct node{
string s;
int num;
}a[2005];
int cmp(node a,node b){
return a.num>b.num;
}
int main(){
int i,j,k;
cin>>n;
for(i=1;i<=n;i++){
cin>>a[i].s>>a[i].num;
}
sort(a+1,a+1+n,cmp);
for(i=1;i<=n;i++)
cout<<a[i].s<<endl;
return 0;
}
/**************************************************************
Problem: 2540
User: neuteam133 []
Language: C++
Result: 正确
Time:4 ms
Memory:2268 kb
****************************************************************/
2541: 优雅的队列
内存限制:128 MB
时间限制:1.000 S
评测方式:文本比较
题目描述
一个队列是由许多的成员构成的,但是这个队列是特殊的,因为队列的成员们都是由 0 和 1 构成的,每个成员都可以用 0 和 1 组成的字符串 S 来表示,例如10、01和11等。现在选出了由 n 个成员组成的队列,为了符合大众的审美标准,一个队列是否优雅是由成员们的排列顺序决定的。
定义队列为优雅的条件为:最终所形成的队列,成员们的排列顺序在字典序上是最小的。
输入
第一行,包含一个整数 n (1 <= n <= 2 * 105)
接下来输入 n 行,每行输入一个二进制字符串 Si 表示为第 i 个成员
输出
输出一个字符串,表示优雅队列的排列情况
样例输入 复制
3
111
000
101
样例输出 复制
000101111
提示
字典序最小的排列应该是 S2S3S1,形成的队列为: 000101111
题解
经典题目啊!!!!!
学过NOIP的不会的,出门吧
应该是07年的题目了!!!
其实思想也是很简单的,你要求做到字典序最小,那你用cmp排序的时候两个数相加和反向相加比较就完事了!!
#include<bits/stdc++.h>
using namespace std;
int n;string s[200005];
bool cmp(string a,string b){
return a+b<b+a;
}
int main(){
int i,j,k;
cin>>n;
for(i=1;i<=n;i++)
cin>>s[i];
sort(s+1,s+1+n,cmp);
for(i=1;i<=n;i++)
cout<<s[i];
cout<<endl;
return 0;
}
/**************************************************************
Problem: 2541
User: neuteam133 []
Language: C++
Result: 正确
Time:13 ms
Memory:8568 kb
****************************************************************/
cmp是关键!!可以积累!!
2543: 分享
内存限制:128 MB
时间限制:1.000 S
评测方式:文本比较
题目描述
ACM社团是一个相亲相爱的大家庭,acmer都热衷于分享自己的美食给其他人品尝。
现在有n个acmer,编号从0至n-1,最初acmeri手中有ai份美食.
他们将按照 i = 1,2,3,4,5,…,m 的顺序执行一下操作:
(1)设置变量c为0
(2)将bi手中的所有美食放在空桌子上
(3)重复一下过程,直至桌子上的美食用尽:
将c的值增加1
将桌子上的一份美食给编号为(bi+c) mod n的acmer
求操作结束后每个acmer手中的美食份数
输入
输入格式如下:
n m
a0 a1 … an-1
b1 b2 … b3
1≤ n≤ 105
1≤ m≤ 105
1≤ ai≤ 105
1≤ bi≤ 105
输出
一行,输出n个整数,顺序表示acmer手中的美食份数
样例输入 复制
5 3
1 2 3 4 5
2 4 0
样例输出 复制
0 4 2 7 2
提示
样例解释
题解
很迷茫,但是我感觉就是前缀和,但是你有没办法绕一个环,而且可能分配不止一圈。考场上写了暴力算法。下面是考场写的暴力,超时了哈
#include<bits/stdc++.h>
using namespace std;
int n,m,a[100005],s[100005];
int main(){
int i,j,k;
cin>>n>>m;
for(i=0;i<n;i++)
cin>>a[i];
while(m--){
int now;cin>>now;
int x=a[now];
for(j=1;j<=x;j++)
a[(now+j)%n]++;
a[now]-=x;
}
for(j=0;j<n;j++)
printf("%d ",a[j]);
printf("\n");
return 0;
}
/**************************************************************
Problem: 2543
User: neuteam133 []
Language: C++
Result: 答案错误
****************************************************************/
2534: 优化∑
内存限制:128 MB
时间限制:1.000 S
评测方式:文本比较
题目描述
在竞赛中经常会出现双重求和并且不能以O(n2)的时间复杂度实现,这就需要我们去掌握优化∑的能力。
现给定长度为n的正整数数组a、长度为m的正整数数组b、正整数c,求
输入
第一行三个正整数n、m、c
第二行n个正整数,表示正整数数组a
第二行m个正整数,表示正整数数组b
1≤ n≤ 105
1≤ m≤ 105
1≤ c≤ 105
1≤ ai bi≤ 105
输出
一个整数表示最终答案,答案请对109+7取模
样例输入 复制
5 5 5
1 1 1 1 1
2 2 2 2 2
样例输出 复制
250
题解
这道题,算数学???
你不行展开看看呢??
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int mod=1000000007;
int n,m,c;
int a[100005],b[100005];
signed main(){
int i,j,k;
cin>>n>>m>>c;
for(i=1;i<=n;i++)
cin>>a[i];
int sum=0;
for(i=1;i<=m;i++){
cin>>b[i];
sum+=b[i];
}
sum=sum*c%mod;
int res=0;
for(i=1;i<=n;i++)
res=(res+a[i]*sum)%mod;
cout<<res<<endl;
return 0;
}
/**************************************************************
Problem: 2534
User: neuteam133 []
Language: C++
Result: 正确
Time:50 ms
Memory:3740 kb
****************************************************************/
2545: min
内存限制:128 MB
时间限制:1.000 S
评测方式:文本比较
题目描述
给你一颗有n个顶点的树,顶点的编号为1到n,第i条边连接ai和bi
再给你一个长度为N的整数序列
,设顶点a、b之间的边数为d(a, b)
令
的权值表示为,求
输入
输出
一个整数,表示最终答案
样例输入 复制
4
1 2
1 3
2 4
1 1 1 2
样例输出 复制
5
提示
例如考虑f(1),画图可得d(1, 1)=0、d(1, 2)=1、d(1, 3)=1、d(1, 4)=2, 所以 f(1) = 0×1+1×1+1×1+2×2=6.
题解
不会做
2535: xc的game
内存限制:128 MB
时间限制:1.000 S
评测方式:文本比较
题目描述
小胡和小周在玩游戏,游戏的规则如下:现在有 2 堆石子,各有 a,b 颗石子。两人轮流从任意一堆数量不为0石子堆中取走任意数量的石子,小胡先取。取走最后一颗石子的人获胜。
假如双方都足够聪明,一定会采取当前局面下的最优策略,游戏的最终获胜者是谁?
输入
两个整数,分别代表a,b (0 < a, b < 1e9)
输出
如果最终小胡获胜,则输出"hlyyds!!!“,如果最终小周获胜,则输出"xbyyds!!!”
样例输入 复制
2 1
样例输出 复制
hlyyds!!!
提示
小胡先取走第一堆石子中 1颗石子,此时第一堆石子剩余1颗,第二堆石子剩余1颗,那么无论小周怎么拿,都是小胡获胜
题解
这道题再次鸣谢 张老师,非常感谢大佬找到的规律
至于原理(来自 文心一言)
这个问题是一个经典的博弈问题,通常称为Nim游戏。在这个游戏中,两位玩家轮流从任意一堆非空石子中取走任意数量的石子,直到所有石子都被取完,取走最后一颗石子的玩家获胜。
Nim游戏有一个非常著名的必胜策略,称为Grundy数或Nim和。在这个特定的游戏中,每堆石子的数量可以看作是一个二进制数中的一位。玩家每次操作可以看作是改变这些二进制位。必胜的策略是确保每次轮到对手操作时,所有石子堆的石子数量的异或和(XOR sum)为0。如果当前所有石子堆的异或和已经是0,那么无论对手如何操作,你都可以通过相应的操作使得下一轮所有石子堆的异或和再次变为0。
具体到这个问题:
如果初始时,两堆石子的数量a和b的异或结果为0(即a XOR b = 0),那么无论小胡如何操作,小周都可以通过一次操作使得剩下的石子堆的异或和再次变为0,并最终取得胜利。
如果初始时,a XOR b ≠ 0,那么小胡可以通过第一次操作使得剩下的石子堆的异或和变为0(他可以选择从a或b中取走一定数量的石子,使得a和b的异或结果变为0)。之后,无论小周如何操作,小胡都可以通过相应的操作维持异或和为0的状态,直到最后取走最后一颗石子获胜。
因此,对于这个问题,我们只需要检查初始时a和b的异或结果:
如果a XOR b = 0,则输出"xbyyds!!!"(小周获胜)。
否则,输出"hlyyds!!!"(小胡获胜)。
对于样例输入2 1,因为2 XOR 1 = 3 ≠ 0,所以小胡有必胜策略,输出应为"hlyyds!!!"。
#include<bits/stdc++.h>
using namespace std;
#define int long long
signed main(){
int a,b;
cin>>a>>b;
if(a!=b)printf("hlyyds!!!\n");
else printf("xbyyds!!!\n");
return 0;
}
/**************************************************************
Problem: 2535
User: neuteam133 []
Language: C++
Result: 正确
Time:3 ms
Memory:2176 kb
****************************************************************/
感谢一位作者文章让我理解,记录下地址。万分感谢
https://blog.csdn.net/a_forever_dream/article/details/104811240