蓝桥杯:乘积最大 C/C++解法
题目描述
给定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
【输出格式】
一个整数,表示答案。
【输入样例1】
5 3
-100000
-10000
2
100000
10000
【输出样例1】
999100009
【输入样例2】
5 3
-100000
-100000
-2
-100000
-100000
【输出样例2】
-999999829
解题思路
这道题可以用DP去解决。首先,求出前 i 项中最大值以及前 i 项乘积,这样的好处是在之后的递归中可以节省时间。之后调用dp_func()函数进行乘积计算。
dp_func()函数原理:
从 n 项中选出 k 个数的最大乘积等同于
1>从 n-1 项中选出 k 个数的最大乘积
或 2>从 n-1 项中选出 k-1 个数的最大乘积再乘以第 n 个数
之后 1> 和 2> 比较大小,选择乘积大的作为答案 (以此类推用递归法写)
注意事项: 数字乘积比较大,用 long long 进行存储,最后求模
代码实现
#include <bits/stdc++.h>
using namespace std;
#define MAXLEN 100009 /* 100009太大了,编译器可能报错,
编译时改小,代码提交时要改回来 */
typedef long long ll;
ll a[MAXLEN];
ll dp[MAXLEN][MAXLEN];
int b[MAXLEN][MAXLEN]={0}; //标记dp[][]二维数组中项 是否被赋值 赋值后为 1
int mod_self(ll x) // 求余函数
{
if(x>=0) return x%1000000009;
else return (0-((0-x)%1000000009));
}
/*
len表示总数量,cat表示拿的数量
此函数功能为求出最大乘积
*/
ll dp_func(int len, int cat)
{
if(cat<=len)
{
if(b[len][cat]) return dp[len][cat];
else
{
dp[len-1][cat-1]=dp_func(len-1,cat-1); // 前len-1中取cat-1个数
dp[len-1][cat]=dp_func(len-1,cat); // 前len-1中取cat个数
dp[len][cat]=1;
if(dp[len-1][cat] > (dp[len-1][cat-1]*a[len]))
return dp[len][cat]=dp[len-1][cat];
else
return dp[len][cat]=dp[len-1][cat-1]*a[len];
}
}
}
int main()
{
int n,k;
ll max,sum=1;
cin >> n >>k;
for(int i=1;i<=n;i++)
cin >> a[i];
for(int i=1;i<=n;i++) // 找出前i项中最大值
{
max=a[i];
for(int j=i+1;j<=i;j++)
if(max<a[j]) max=a[j];
dp[i][1]=max;
b[i][1]=1;
}
for(int i=1;i<=n;i++) //计算前i项的乘积
{
sum*=a[i];
dp[i][i]=sum;
b[i][i]=1;
}
cout << mod_self(dp_func(n,k));
return 0;
}
博客介绍了如何使用动态规划和递归法解决蓝桥杯竞赛中的一道题目,目标是找出给定整数数组中K个数的最大乘积,并考虑了数值可能为负的情况。解题思路包括计算前i项的最大值和乘积,然后通过比较选择较大的乘积进行递归计算,最终结果需对1000000009取模。
1751

被折叠的 条评论
为什么被折叠?



