西安邮电大学2020.12.19ACM新生赛题解(部分)
A题:永远的王聪明王
难易程度:简单
描述
一天,聪明王在家中写作业,一共有n门课的作业,现在他知道自己写完每门作业的时间。他的妈妈可能随时会回来,他想在他的妈妈回来时尽可能的写完多的科目(显得自己很努力),他该如何安排写作业的顺序呢?聪明的你帮他安排一下吧。
输入
第一行输入一个数n,接下来n行,每行有两个输入,第一个是科目名称,第二个是一个整数x,表示完成这门课所需要时间。1≤n≤10 6,1≤x≤10 6 ,输入保证科目名称不会超过100个字符、各科目所需的时间都不相同
输出
输出一行,n个科目名称,代表完成作业的顺序
题解:
算法思想:结构体排序
据题意:先做完时间短的作业,因此只需对时间排序即可。(PS:注意所给的数据范围,时间复杂度不超过O(Nlogn)
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int time;
char name[105];
}subject;//创建结构体
subject num[1000005];//结构体数组
int cmp(const void* a, const void* b)
{
return ((subject*)a)->time - ((subject*)b)->time;
}
int main()
{
int n;
scanf("%d", &n);
for (int i = 0; i < n; ++i) {
scanf("%s%d", num[i].name, &(num[i].time));
}
//排序函数对结构体中的time进行排序
qsort(num, n, sizeof(subject), cmp);
//输出结构体中的name
for (int i = 0; i < n; ++i) {
printf("%s ", num[i].name);
}
return 0;
}
F题:菊花侠大战桃花怪
难易程度:中等(个人感觉难在分析题目部分)
描述
输入
输出
占一行,Win或Lose
提示
题解
算法思想:博弈论
比较有意思的博弈论,可以通过假设法证得,一定是先手必胜;也可以自己模拟几组,发现永远是先手先胜,所以直接输出Win即可。
#include<stdio.h>
int main() {
int n;
scanf("%d", &n);
printf("Win\n");
return 0;
}
I题:我就试一下题目名字可以出多长没想到这名字真的可以出这么长真的是太厉害了所以我把这道题就叫做小植哥哥の好奇吧好嘛qwq
难易程度:简单
描述:
军旅情怀,潇湘冷月。
当白云与蓝天相遇,白云便多了一份宽广,蓝天又增了一份柔情;
当青山与流水相遇,青山便多了一份细腻,流水又增了一份坚毅。
又是一年军训季,小植哥哥走过操场边。“学妹!”他无意瞥了一眼操场,惊呼道:“是学妹!”顺眼望去,原来是学妹们在训练。同行的玄玄哥哥已经在催着他走了,可这小植哥哥的心却早都定在了操场,他拉住玄玄哥哥准备坐下来慢慢欣赏细细品味。
小植哥哥看了一会,发现教官并没有让学妹们训练,而是在跟她们玩游戏。教官让学妹先在跑道上蹲成一列,给每个学妹从前到后按 1,2,3,4…1,2,3,4… 这样的顺序编号 ,然后教官开始说一个数字 kk ,这时编号为 kk 的倍数的学妹如果是站着,就要蹲下;如果是蹲着,就要站起来。教官看起来人非常好,他没有为难学妹,选择了按 1,2,3,4…1,2,3,4… 这样按顺序报数字。小植哥哥突然好奇,在教官喊了 mm 次后,哪几个人是站着的,旁边的玄玄突然憨了,因为他也不知道,但是他不能没有面子,于是他求求你告诉他还有谁是站着的(玄玄哥哥:qwq)
输入
输入一个数 mm
输出
若干数,表示站着的学妹的编号
提示
题解
算法思想:数学
简单分析可知。只有编号为平方数的学妹会站起来,因为只有平方数的因子是奇数个,即平方数编号的学妹会进行奇数次操作,因此一定会站着。
(PS:个人体会,双层嵌套的for循环会超时)
#include<stdio.h>
int main() {
long int m;//学妹的数量
scanf("%ld", &m);
long int i;
for (i = 1; i*i <= m; i++) {
printf("%ld ",i*i);
}
return 0;
}
L题:菜学长的糖糖
描述
菜学长有一堆糖糖,菜学长的糖糖都有自己的标号并且同一个标号的糖糖总是有偶数个,但是有一天被贪吃的学姐偷吃掉了一个,菜学长很生气,你能帮菜学长找出这个糖糖的标号吗?
输入
第一行一个数n(3<=n<=1000),接下来n个数代表菜学长有n个糖糖ai(可以知道输入的n总是奇数),后面n个数代表每个糖糖的标号。(0<=ai<=1e9)
输入
输出被偷吃掉的糖糖的标号。
题解
思路:位运算,异或运算符合交换律,相同数字异或答案为0,将所有数字异或起来输出即可。
#include<stdio.h>
int a[10001];
int main(){
int n;
scanf("%d",&n);
int i;
for(i=1;i<=n;i++){
scanf("%d",&a[i]);
}
int s=a[1];
for(i=1;i<n;i++){
s=s^a[i+1];
}
printf("%d",s);
return 0;
}
M题:水题
难易程度:简单
描述
菜学长和糖糖做游戏,菜学长给出了一条从0开始的整数数轴,并在数轴上标出了一点A(坐标为n),要求糖糖在数轴上找出一点B使得从0到B的距离与从A到B的距离相差K。糖糖很快发现B点并不总是存在,于是菜学长允许糖糖将A点左移或右移一个单位。请问糖糖最少移动几次A点就能找到B点?
输入
第一行包含一个整数t (1≤ t ≤6000),代表测试个数。
第二行包含两个整数n和k (0 ≤ n,k ≤1000000)
输出
输出:
t行,每行输出移动的最小次数。
题解
如果k==n,则A和B重合或者B在A右边即可,移动步数为0;
如果k>n,A需移动到k点才可;
如果k<n,则B可能在A的左边找到,如果k,n奇偶性相同则不需要移动,否则A点要向右移动1步。
#include<stdio.h>
typedef struct{
int n;
int k;
}wuhu;
wuhu num[1000000];
int a[100000];
int main(){
int i,t;
scanf("%d",&t);
for(i=1;i<=t;i++){
scanf("%d%d",&num[i].n,&num[i].k);
}
for(i=1;i<=t;i++){
if(num[i].k==num[i].n){
a[i]=0;
}
if(num[i].k>num[i].n){
a[i]=num[i].k-num[i].n;
}
if(num[i].k<num[i].n){
if(num[i].n%2==0){
if(num[i].k%2==0) a[i]=0;
else a[i]=1;
}
else{
if(num[i].k%2==1) a[i]=0;
else a[i]=1;
}
}
}
for(i=1;i<=t;i++){
printf("%d",a[i]);
printf("\n");
}
return 0;
}