试题 历届真题 乘积最大【第九届】【省赛】【B组】

该博客主要讨论如何从给定的一组整数中选择K个数,使得它们的乘积最大。文章详细介绍了不同情况下的策略,如全正数、全负数、一正多负、一负多正等,并提供了Java实现的解决方案,该方案能够处理各种边界情况,确保找到最大乘积并正确取模。
摘要由CSDN通过智能技术生成

试题 历届真题 乘积最大【第九届】【省赛】【B组】

资源限制
时间限制:1.0s 内存限制:256.0MB
  给定N个整数A1, A2, … AN。请你从中选出K个数,使其乘积最大。

请你求出最大的乘积,由于乘积可能超出整型范围,你只需输出乘积除以1000000009的余数。

注意,如果X<0, 我们定义X除以1000000009的余数是负(-X)除以1000000009的余数。
  即:0-((0-x) % 1000000009)
输入格式
  第一行包含两个整数N和K。
  以下N行每行一个整数Ai。

对于40%的数据,1 <= K <= N <= 100
  对于60%的数据,1 <= K <= 1000
  对于100%的数据,1 <= K <= N <= 100000 -100000 <= Ai <= 100000
输出格式
  一个整数,表示答案。
样例输入
5 3
-100000
-10000
2
100000
10000
样例输出
999100009

再例如:
样例输入
5 3
-100000
-100000
-2
-100000
-100000
样例输出
-999999829

资源约定:
峰值内存消耗(含虚拟机) < 256M
CPU消耗 < 1000ms

请严格按要求输出,不要画蛇添足地打印类似:“请您输入…” 的多余内容。

注意:
main函数需要返回0;
只使用ANSI C/ANSI C++ 标准;
不要调用依赖于编译环境或操作系统的特殊函数。
所有依赖的函数必须明确地在源文件中 #include
不能通过工程设置而省略常用头文件。

提交程序时,注意选择所期望的语言类型和编译器类型。
看这个

import java.util.Arrays;
import java.util.Scanner;
 
public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int k = sc.nextInt();
        long[] num = new long[k];
        long[] a = new long[n];
        for (int i = 0; i < n; i++)
            a[i] = sc.nextInt();
        Arrays.sort(a);
        //负数个数
        int countfu = 0; 
        for (int i = 0; i < n; i++)
            if (a[i] < 0)
                countfu++;
        //正数个数
        int countz = n - countfu; 
 
        //全为正(取奇/偶数个)、全为负且取奇数个、一负多正(取奇/偶数个)、
        if (countfu == 0 || countfu == n && k % 2 == 1 || countfu == 1) 
            for (int i = 0; i < k; i++)
                num[i] = a[n - 1 - i];
 
        //全为负且取偶数个、一正多负且取偶数个
        if (countfu == n && k % 2 == 0 || countz == 1 && k % 2 == 0) { 
            for (int i = 0; i < k; i++)
                num[i] = a[i];
        }
 
        //一正多负且取奇数个
        if (countz == 1 && k % 2 == 1) { 
            num[0] = a[n - 1];
            for (int i = 1; i < k; i++)
                num[i] = a[i - 1];
        }
 
        //多正多负且取偶数个(两两一对,按对取)
        if (countz > 1 && countfu > 1 && k % 2 == 0) { 
            int i = 0, j = n - 1, x = 0;
            for (int p = 0; p < k / 2; p++) {
                if (a[i] * a[i + 1] > a[j] * a[j - 1]) {
                    num[x++] = a[i++];
                    num[x++] = a[i++];
                } else {
                    num[x++] = a[j--];
                    num[x++] = a[j--];
                }
            }
        }
 
        //多正多负且取奇数个(先把最大的正数留出来)
        if (countz > 1 && countfu > 1 && k % 2 == 1) { 
            int i = 0, j = n - 2, x = 0;
            for (int p = 0; p < k / 2; p++) {
                if (a[i] * a[i + 1] > a[j] * a[j - 1]) {
                    num[x++] = a[i++];
                    num[x++] = a[i++];
                } else {
                    num[x++] = a[j--];
                    num[x++] = a[j--];
                }
            }
            num[x] = a[n - 1];
        }
 
        long res = 1;
        for (int i = 0; i < k; i++) {
            res *= num[i];
            res %= 1000000009;
        }
        System.out.println(res);
    }
 
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

超好的小白

没体验过打赏,能让我体验一次吗

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值