2022.04.20华为笔试

严正声明:转载请注明出处!!!

总结一下做题的过程:
刚开始以为第一题很简单,因为忽略了一个很重要的条件,再去读题发现没注意到那个要点,然后开始重来,发现下不了笔,整个人都傻了。整个一大惨败,前一个小时根本没思路,一个小时后发现可以分情况考虑,但是当时又遇到了一个问题,就是不知道怎么去分是否要退出的情况。做完第一题剩下10几分钟,直接交卷了,麻了……
第二题没怎么看,感觉是这三题里面最难的。
最后一道题感觉用回溯可以做,但是我由于时间剩得不多了,当时比较慌,找不到递归出口的条件,下来跟他们讨论了一下这个题,说是要么需要遍历一遍,要么就是建树,但是我觉得这题可以直接看作是没有回路的图。但是呢,想到他们说2022.4.13那次的最后一题用回溯做完过了5%,原因是超时,就心态崩了,还是果断放弃,直接System.out.println(-1);过了10%,溜了溜了……

题目描述:小聪入职新公司,参加线上的新员工必备考试,考试共25题,依次是10个判断题(每题2分)、10个单选题(每题4分)和5个多选题(每题8分),总分100分。
考题只能顺序作答,答对题目获得相应的分数,答错题目获得0分,考试系统不提示作答是否正确,答题过程中如果累积有3道题答错,直接中止考试并计算考试分数。
小聪考试结果是N分(0<=N<=100),请根据小聪的分数,算出所有可能的答题情况的个数。
输入

整数,表示小聪的考试得分N,N为偶数,0<=N<=100(N不会是不可能考出来的分数)。

输出

整数,表示所有可能的答题情况的个数

样例1

输入:94
输出:100
解释:有1道判断题和1道单选题答错,其余的题都答对

样例2

输入:100
输出:1
解释:所有的都答对

思路
三种情况:

  1. 如果分数N <= 18的话只能是全是判断题
  2. 如果分数N在20到58之间可以是判断+单选
  3. 如果分数N >= 60可以是判断+单选+多选

比如:

  • 16的时候只能是8个判断,18的时候只能是9个判断
  • 20的时候可以是 10判或者8判+1单,22的时候是9判+2单
  • 56的时候可以是8判+10单,58的时候可以是9判+10单
  • 60的时候可以是10判+10单或者10判+8单+1多,62的时候是9判+9单+1多
    找到这几个边界的数据,就可以推断出上面的三个区间。

设判断题个数为x,单选个数为y,多选个数为z

  1. 如果全是判断题,那2x = N, x = N / 2
  2. 如果判断题+单选题,那就是2x + 4y = N,x可以是8,9,10,y = (N - 2x) / 4
  3. 如果是判断+单选+多选,那就2x+4y+8z = N

x可以是8,9,10
当x = 8时,y只能是10
当x = 9时,y可以是9,10
当x = 10时,y可以是8,9,10
z = (N - 2x - 4y) / 8

比如:情况3 且x = 9时,判断错了一道,单选只能错1道或者0道,如果单选错了2道的话,就直接结束了,就没有答对的多选题了。这种是属于第2种情况,判断题对9道,单选对8道,总分是9 * 2 + 8 * 4 = 50
综上可以根据N计算出x,y,z。
然后根据x,y,z计算可能的答题组合。

第一种情况:2x = N
当x 为8,9,10的时候,即最多错2道,就是10道题中选择x道题,结果就是组合数C(10, x)
如果x < 8,这种情况要注意,不能是C(10, x),比如x=2时,最多只能做到第4题,第五题肯定是错的,如果第五题是对的,那至少也对了3道题。所以结果应该是C(x + 2, x)。此注意的点对下面的两种情况都满足。

第二种情况:2x + 4y = N
当x为8时,计算出y,如果y不是整数,那这个组合无效。如果y为整数,就符合条件,比如56分时x = 8,y = 10
那结果就是C(10, x) * C(10, y),这里计算C时跟上一步说的一样,要考虑中途结束答题的情况。
此时又有个注意的点,比如当x = 8时,y = 5时,y只能是单选题的前5个,因为判断题已经错了两个了,如果单选题前5个中间再错一个就结束答题了,所以就算y的组合数的时候,应该是C(y, y) = 1,而不是C(y + 2, y)。结果是C(10, x) * C(y, y)。
再比如当x = 9时,y = 5的话,单选题的前5个里只能错1个,组合数就是C(y + 1, y),结果是C(10, x) * C(y + 1, y)
然后把x的三种情况的结果相加就是最后的结果。

第三种情况和第二种类似,只是计算z的时候要先根据x把y的范围找出来,再把y的可能列出来,再去计算z。
下面截图框出来的部分就是处理上面说的注意的点。
在这里插入图片描述

代码

import java.util.*;
public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int N = sc.nextInt();
        int count = 0;
        if(N <= 18){
            int x = N / 2;
            int y = 0;
            int z = 0;
            count = count(x, y, z);
        }else if(20 <= N && N <= 58){
            int[] xArr = {8, 9, 10};
            for(int x: xArr){
                int r = (N - 2 * x) % 4;
                if(r != 0){
                    continue;
                }
                int y = (N - 2 * x) / 4;
                count += count(x, y, 0);
            }
        }else if(60 <= N){
            int[] xArr = {8, 9, 10};
            for(int x: xArr){
                int[] yArr = {10};
                if(x == 9){
                    yArr = new int[]{9, 10};
                }
                if(x == 10){
                    yArr = new int[]{8, 9, 10};
                }
                for(int y: yArr){
                    int r = (N - 2 * x - 4 * y) % 8;
                    if(r != 0){
                        continue;
                    }
                    int z = (N - 2 * x - 4 * y) / 8;
                    count += count(x, y, z);
                }
            }
        }
        System.out.println(count);
    }
    public static int count(int x, int y, int z){
        int m1 = x + 2;
        if(m1 > 10){
            m1 = 10;
        }
        int m2 = y + (2 - (10 - x));
        if(m2 > 10){
            m2 = 10;
        }
        int m3 = z + (2 - (10 - x) - (10 - y));
        if(m3 > 5){
            m3 = 5;
        }
        int c1 = c(m1, x);
        int c2 = c(m2, y);
        int c3 = c(m3, z);
        return c1 * c2 * c3;
    }
    public static int c(int m, int n){
        int sum1 = 1;
        for(int i = 1;i <= n;i++){
            sum1 = sum1 * i;
        }
        int sum2 = 1;
        for(int j = m;j >= m - n + 1;j--){
            sum2 = sum2 * j;
        }
        return sum2 / sum1;
    }
}

期待有更好思路的你们提供更优的方法。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值