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

该博客讨论了一个算法问题,即如何从给定的一组整数中选择K个数,使得它们的乘积最大,并考虑了乘积可能超出整型范围的情况。博主分享了一种解决方案,通过排序和贪心策略来找到最大的乘积,特别处理了负数的情况。代码实现使用了Python,并成功通过了所有评测点。
摘要由CSDN通过智能技术生成
资源限制

内存限制:256.0MB C/C++时间限制:1.0s Java时间限制:3.0s Python时间限制:5.0s

问题描述

给定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
不能通过工程设置而省略常用头文件。

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

!!!

前面一直想着分情况来看,然后再试试贪心,结果写了很长一串代码,只过了六个评测点,实在是找不到哪里错了。后面看了大佬的做法,我的理解可能不是很对,但是所有评测点都通过了,建议看看大佬的文章。传送门
下面附上自己python实现的代码:

n, k = map(int, input().split())
arr = [0]*n

mod = 1000000009
res = 1 # 记录结果

for i in range(n):
    arr[i] = int(input())
arr = sorted(arr) # 把列表排序
l = 0; r = n-1
sign = 1 # 这个的作用主要是区分到底是要乘积最大还是乘积最小
# 如果k为偶数
# 1.max <= 0 乘积从0->k-1 取两两乘积最大
# 2.max > 0 从左右两边各取两个相乘取最大值
# 如果k为奇数
# 1.max < 0 乘积从n-k -> n-2,也就是就两两乘积最小,已经排序过所以取最右边的k-1个数再乘上n-1
# 2.max >= 0 从0 -> n-2 两边取两个相乘取最大值与 n-1相乘
if k%2:
    res = arr[r] # k 为奇数取n-1
    r -= 1
    k -= 1
    if res < 0: # 判断列表中是否全为负数,是则后面两两乘积取最小的
        sign = -1 # 两个负数相乘,负数小的后乘积大,想要乘积小的两个数,要乘-1再做比较
while k:
    x = arr[l] * arr[l+1] # 左边两个数的乘积
    y = arr[r] * arr[r-1] # 右边两个数的乘积
    if x * sign > y * sign:# 判断那个乘积大
        res *= x
        l += 2
    else:
        res *= y
        r -= 2
    k -= 2


if res > 0:
    res %= mod
else:
    res = 0 - ((0 - res)%mod)

print(res)

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值