计挑-21-编程4

某游戏公司设计了一个奖励活动,给N个用户(1≤N≤10^7)连续编号为1到N,依据用户的编号S发放奖励。
发放奖励规则为:
公司随机设定三个非零正整数x,y,z。
如果S同时是x、y的倍数,奖励2张卡片;
如果S同时是y、z的倍数,奖励4张卡片;
如果S同时是x、z的倍数,奖励8张卡片;
如果S同时是x,y,z的倍数奖励10张卡片;
其他奖励1张卡片;
以上奖励不能同时享受。满足多个奖励条件时,以最高奖励为准。
求任意连续的L个用户,使得这L个用户得到的奖励总和最多,输出奖励总和的值。

输入说明:第一行,输入N,L,以空格隔开;(1≤L≤N≤10^7)
第二行,输入x,y,z,以空格隔开;(1≤x,y,z≤L)
输出说明:符合条件的连续L个用户的奖励总和的最大值。
输入样例:40 7
3 5 2
输出样例:24

其实这就是个组合题:求最小公倍数+找到长度为K的最大子数组(滑动窗口)

啊正好是今天的每日一题,还正好是我没做出来的,さいこう!

需要注意的是,这里N、L的最大值是10^7,所以不可能使用原始的保存长度N、L的数组,这里必须做空间优化
好吧,我认真想过过了,没法,没想到除了 用一个长度L的数组+滑动窗口 外更好的做法

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer stringTokenizer = new StringTokenizer(br.readLine());

        int n = Integer.parseInt(stringTokenizer.nextToken());
        int l = Integer.parseInt(stringTokenizer.nextToken());
        String str = br.readLine();
        int x = Integer.parseInt(str.substring(0,1));
        int y = Integer.parseInt(str.substring(2,3));
        int z = str.charAt(4)-48;

        // 用队列来保存子数组
        Deque<Integer> nums = new ArrayDeque<>(l);

        // 生成一个序列,然后求连续序列的最大和
        int xy = leastCommonFactor(x,y);
        int yz = leastCommonFactor(y,z);
        int xz = leastCommonFactor(x,z);
        int xyz = leastCommonFactor(xy,z);

        // preCard用来记录滑动窗口头的卡片数量
        int maxSum = 0,tempCard;

        for(int i=1;i<=n;i++){
            // 计算卡片所得
            if(i%xyz==0) tempCard=10;
            else if(i%xz==0) tempCard=8;
            else if(i%yz==0) tempCard = 4;
            else if(i%xy==0) tempCard =2;
            else tempCard =1;
            // 开始滑动窗口
            // 初始化滑动窗口
            // 这里统一假设题目给的值合法,所以就不做参数检查
            if(i<=l){
                nums.add(tempCard);
                maxSum+=tempCard;
            }
            else {
                nums.remove(nums.getFirst());
                nums.add(tempCard);
                int tempSum=0;
                for(int j:nums) tempSum+=j;
                maxSum = Math.max(tempSum,maxSum);
            }
            // System.out.print(tempCard+" ");
        }
        System.out.println(maxSum);
    }

    /**
     * 求最小公倍数
     */
    public static int leastCommonFactor(int a,int b){
        int product = a*b;
        // 使用辗转相处法求最大公因数
        while((a*b)!=0){
            // 这里随便把==写到哪个情况里覆盖相等的情况
            if(a>=b) a%=b;
            else b%=a;
        }
        return a>b?product/a:product/b;
    }
posted @ 2022-11-23 10:28  YaosGHC  阅读(84)  评论(0)    收藏  举报