2024大连东软信息学院 “星巴克杯“ 校程序设计竞赛

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

  • 6
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

徐苏洋

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值