当前位置: 代码迷 >> 综合 >> HAUT OJ 新生周赛 三 反思总结
  详细解决方案

HAUT OJ 新生周赛 三 反思总结

热度:94   发布时间:2023-12-04 03:20:10.0

问题 A: 卷王之争

问题描述:

身为新一届的大佬,H同学和T同学两个人开始竞争卷王之位。

H同学说:我每周抽a/b的时间用来学习,我是卷王!

T同学说:我每周x/y的时间都在学习,比你多,我才是卷王!

H同学不服气,反驳道:明明我比你学习时间多,我才是!

现在,他们两个想知道,到底谁的学习时间多。

输入

一行四个非负整数,a,b,x,y
(a<=b,x<=y ,< a,b,x,y <= 100 000 000,  b , y不等于0)

输出

如果小H的学习时间多,输出"H is juanwang!" ;
如果小T的学习时间多,输出"T is juanwang!" ;
如果两人学习时间一样多,输出"We are juanwang!" ;
(输出不带引号)

样例输入

1 2 3 4

样例输出 

T is juanwang!




原因分析:

1. 第一次开了的精度太大了 (1e-6),应该尽量开大点 1e-20;

2. double不能直接判等号.(由于浮点型的精度是有限的,经过运算就可能存在舍入误差)

 3.还可以通过 通分直接比较分子大小,避免了上述问题.(更精准)




解决方案:

1.精度确定个范围


#include <iostream>
#include <algorithm>
#include <cmath>#define double long doubleconst double eps = 1e-20 ;int dcmp(double x,double y){if(fabs(x - y ) < eps) return 0 ;if(x < y) return -1;return 1 ;
}
int main()
{double a,  b , x , y ;scanf("%d%d%d%d" ,&a ,&b ,&x ,&y) ;double s = a/b ;double u = x/y ;if(dcmp(s,u) > 0)printf("H is juanwang!\n") ;else if(dcmp(s,u) < 0)printf("T is juanwang!\n") ;elseprintf("We are juanwang!\n") ;return 0 ;}

2. 通分

#include <iostream>int main()
{long long a , b , x , y ;scanf("%d%d%d%d",&a,&b,&x,&y) ;a*= y ;x*= b ;if(a > x)printf("H is juanwang!\n") ;else if(a < x)printf("T is juanwang!\n") ;elseprintf("We are juanwang!\n") ;return 0;
}

问题 B: 纸牌游戏(待更新)

问题描述:

众所周知,acmer们打纸牌,输了是要写题解的。


S学长因为打纸牌输了很多题解,现在S学长想玩一个纸牌游戏挑战新生。

游戏规则是这样的:

一副纸牌有54张,这个游戏我们暂且不要大小王,则游戏中我们有52张纸牌可以使用,共四种花色,每种花色13张纸牌。

游戏开始两个人轮流取走纸牌,规定每人每次可以取走任意花色的纸牌最多n张,并且每次取走的这些纸牌只能是同种花色,(不必与对方取的纸牌花色一样),不可以不取;

最后没有纸牌可以取的一方为失败者

S学长想让让新生,所以让对方可以先取。

因为S学长是绝顶聪明的,为了能赢过他,必须采取的是最优策略。

输入:

一个整数n(1<= n <=13),代表每次可以取走的最多纸牌数。

输出:

如果新生可以赢得s学长,输出“%%%” ;

如果新生输了,输出“tql” ;

样例输入:

10

样例输出:

tql

原因分析:


解决方案:

#include <stdio.h>int main()
{printf("tql") ;return 0;
}

问题 C: 签到时间
   


问题描述: 

出题人说是时候要给新生赛出一道签到题了,但她并不想让所有的新生都能签到()。

 

已知出题人很喜欢偶数,所以出题人想要在所有参赛人中选偶数个同学让他们签到成功。

现有n个参赛人,编号分别为1~n。

现在出题人开始挑选m个同学了。(m > 0)

若选出的m个同学数量是偶数,她将视为这是一个好方案;如果是奇数,则是一个坏方案。

出题人现在想知道好方案与坏方案的差是多少。

输入:

一个整数n,代表参赛人数。(n <= 1e6)

输出:

输出好方案与坏方案的差。

样例输入:

4

样例输出:

-1


原因分析:

奇数项的系数和即 C(n,1)+C(n,3)+C(n,5)......  =   偶数项的系数和 C(n,0)+C(n,2)+C(n,4)......

而题目要求 C(n,2)+C(n,4)...... - [  C(n,1)+C(n,3)+C(n,5)......   ]

即 偶数项少了个 C(n,0) 即最后结果为 -1

解决方案:

#include <stdio.h>int main()
{printf("-1\n") ;return 0;
}

问题 D: 干饭时间

问题描述:

小R作为一个资深的干饭人,他每次都会抓紧每一分钟的时间去买所有想吃的东西。

这天小R想买的东西有n种,买这n种东西所需要排队等待的时间分别为a1 , a2 , a3 ... an ;

由于,小R又是一个非常懒惰的人,他同一时间最多只会去买两种东西,并且,他需要在买的东西做好之前赶回来,不然他要重新排队购买。

例如,买蛋糕的时间为15min,买饮料的时间为10min,买零食的时间为4min,小R可以去买了蛋糕之后,利用等待的时间去买饮料;虽然买完饮料后,还有5min可以去买零食,但是为了简化问题,小R不会去买零食,而是赶回去等在蛋糕做好之后,他再去买零食,这样,他就省出了单独去买饮料的时间,总时间为15min+4min=19min;


再例如,买蛋糕的时间为15min,买饮料的时间也是15min,当他去买蛋糕时,同时他就不能去买饮料了,因为这样他就不满足在蛋糕做好之前赶回来,所以总时间为30min。

小R是个非常聪明的人,所以他会运用他的智慧,找到买完这些东西要用的最短的时间

请你计算,聪明的小R买完所有他想吃的东西,所用的最短时间。

输入:

一行一个整数n ( n <= 1000 ),代表小R想买的东西的个数。

n个整数a1 , a2 , a3 ... an ,均不大于1000;

输出:

一行一个整数,代表最短的时间。

样例输入:

5
4 1 5 2 3

样例输出:

 9


原因分析:

1.如果数据个数为奇数,则需要特别处理下最后一个数(经过排序后的最后一个数,即最小数)

即    a[n]=0;    当然个数为偶数也不影响.

2. ans+=a[i]; 放到第二个for前,要不然 如果数据为

3

5 5 5 

只会输出 5即只加了最后一个.


解决方案:

#include<bits/stdc++.h>
using namespace std;
int n,a[10000],b[10000];
bool cmp(int a,int b){return a>b;}
int main()
{int i,j,ans=0,mid;cin>>n;for(i=0;i<n;i++)cin>>a[i];a[n]=0;sort(a,a+n,cmp);for(i=0;i<n;i++){if(b[i]==1)continue;else{ans+=a[i];for(j=i+1;j<n+1;j++){if(a[i]>a[j]&&b[i]!=1&&b[j]!=1){b[i]=1;b[j]=1;break;}}}}cout<<ans;}

问题 F: 周赛榜单

问题描述:

周赛的榜单出来啦,21届的成绩真的是太好了。

某人想从新生榜单里选m个人,让他们成为"winner" ;

于是,好奇的某人想知道,选出的这m个人成绩之和最大是多少。

于是,她出了个赛题,让新生们自己算。

输入:

一个整数n(n <= 1e6),代表参加新生赛的新生数。

接下来按榜单顺序输入n个新生的成绩。成绩不大于100。

一个整数t(t <= 1e6),代表某人询问的次数。

接下来t个整数。

输出:

每次询问,给出前m个新生的成绩之和。

样例输入:

5
10 7 5 4 3
2
1 3

样例输出:

10
22

原因分析:

1. 超过1e6 的数据 不能用cin(除非关闭输入输出流),或用scanf


解决方案:

#include<bits/stdc++.h>using namespace std;
#define ll long long
ll s[1000050],n,a[1000050];
int main()
{ll t,x;scanf("%lld",&n);for(int i=1;i<=n;i++){scanf("%lld",&a[i]);s[i]=s[i-1]+a[i];}scanf("%lld",&t);while(t--){scanf("%lld",&x);printf("%lld\n",s[x]);}return 0;
}

问题 H: 三角图形

问题描述:

阿H有六根棍子。

阿H很喜欢三角形,所以,他想知道能不能用这六根棍子组成两个三角形?

为了问题更容易一点,阿H把从大到小排好序的棍子拿给你,请你帮他解决问题。

输入:

六个数,代表阿H六根棍子的长度。(长度小于100)

输出:

能组成三角形, 输出"Yes" ;

反之,输出"No" ;

样例输入:

1 1 1 1 1 1

样例输出:

Yes


 


原因分析:

思路基本没错,就是最后寻找剩下的三根木棍 思路出现问题,可以直接将下标不等于 i,j,k的数据存到另一个数组中.


解决方案:

1. 把剩下的数存到另一个数组里(简单方法)

#include <iostream>
#include <cstdio>int is_right(int a , int b , int c)
{if(c+b > a)return 1 ;return 0 ;
}int main()
{int a[10] ;for(int i = 0 ; i < 6 ; i++)scanf("%d", &a[i]) ;int flag = 0 ;for(int i = 0 ; i < 6 ; i++)for(int j = i+1 ; j < 6 ; j++)for(int k = j+1 ; k < 6 ; k++){int b[5] ;int c = 0 ;for(int p = 0 ; p < 6 ; p++)if(p != i && p != j && p != k)b[c++] = a[p] ;if(is_right(a[i] , a[j] , a[k])==1 && is_right(b[0] , b[1] , b[2])==1){flag = 1 ;break ;}}if(flag == 0)printf("No\n") ;elseprintf("Yes\n") ;return 0 ;
}

2.直接利用3个for找剩下的三根


#include<bits/stdc++.h>using namespace std;
#define ll long long
int main()
{int a[7],i,j,k;for(i=0;i<6;i++)cin>>a[i];for(i=0;i<6;i++){for(j=i+1;j<6;j++){for(k=j+1;k<6;k++){if(a[k]+a[j]>a[i]){int x,y,z;for(x=0;x<6;x++){for(y=x+1;y<6;y++){for(z=y+1;z<6;z++){if(x!=i&&x!=j&&x!=k&&y!=i&&y!=j&&y!=k&&z!=i&&z!=j&&z!=k){if(a[y]+a[z]>a[x]){cout<<"Yes";return 0;}}}}}}}}}cout<<"No";return 0;
}

部分转载cx学姐  %%%cx聚聚

2021HAUT_新生周赛lcx专场(三)_lichenx_的博客-CSDN博客