HAUT OJ 新生周赛 三 反思总结

问题 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 double
 
const 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") ;
    else
        printf("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") ;
    else
        printf("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") ;
    else
        printf("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博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值