P8669 [蓝桥杯 2018 省 B] 乘积最大
2/26更新:
一开始的做法忽略了一点:
题目中强调的是“请你求出最大的乘积,由于乘积可能超出整型范围,你只需输出乘积除以 (即 )的余数”,而不是“取余后最大的乘积”。
整体思路:
先把arr数组按照绝对值降序排序,我们默认把前k个数字的乘积作为ans,如果这个ans是正数,那么直接输出即可;
如果它是负数,就看能不能调整成正数,很显然,每替换一个数字,这个ans都会变小,所以我们只需要进行最多一次替换即可;
如果不能替换成正数的话,那么ans就是后k个数字的乘积。
#include <iostream> #include <stdio.h> #include <algorithm> #include <string> #include <cmath> #define For(i, j, n) for (int i = j; i <= n; ++i) using namespace std; typedef long long LL; const int N = 1e5 + 5; const double INF = -1e10; const LL mod = 1e9 + 9; int n, k; LL a[N]; bool cmp(int a, int b) { return abs(a) > abs(b); } LL get_min() { LL ans = 1; for (int i = n; i >= n - k + 1; i--) { ans = ans * a[i] % mod; } return ans; } LL get_max(int b, int tar) { LL ans = 1; for(int i = 1; i <= k; i++) { if(i != b) { ans = ans * a[i] % mod; } } if(b != -1) ans = ans * a[tar] % mod; return ans; } int main() { scanf("%d%d", &n, &k); for (int i = 1; i <= n; i++) scanf("%lld", &a[i]); sort(a + 1, a + n + 1, cmp); int cnt = 0, p1 = -1, p2 = -1, m1 = -1, m2 = -1; LL ans = 1; for (int i = 1; i <= k; i++) if (a[i] < 0) cnt++; if (cnt & 1) // 绝对值最大的k个数字只能得到负数 { for (int i = k; i; i--) { if (p1 != -1 && m1 != -1) break; if (p1 == -1 && a[i] > 0) p1 = i; if (m1 == -1 && a[i] < 0) m1 = i; } for (int i = k + 1; i <= n; i++) { if (p2 != -1 && m2 != -1) break; if (p2 == -1 && a[i] > 0) p2 = i; if (m2 == -1 && a[i] < 0) m2 = i; } double f1 = INF, f2 = INF; if(m1!=-1&&p2!=-1) f1 = (double)a[p2]/(double)(-a[m1]); if(p1!=-1&&m2!=-1) f2 = (double)(-a[m2])/(double)a[p1]; if (f1==INF&&f2==INF) // 无法得到正数 { ans = get_min(); } if(f1 > f2) ans = get_max(m1, p2); //------------------------------------------------------------------------------------------------------- else if(f1 < f2) //这里不能只写if,否则在无法得到正数的情况下,会把答案从get_min替换成这个get_max ans = get_max(p1, m2); //------------------------------------------------------------------------------------------------------- } else ans = get_max(-1, -1); printf("%lld\n", ans); return 0; }
这是一开始的做法,死活有两个点过不去:
#include <iostream> #include <stdio.h> #include <algorithm> #include <string> #include <cmath> #define For(i, j, n) for (int i = j; i <= n; ++i) using namespace std; typedef long long LL; const int N = 1e5 + 5; const double INF = 1e10; const LL mod = 1e9 + 9; int n, k; LL a[N]; bool cmp(int a, int b) { return abs(a) > abs(b); } LL get_min() { LL ans = 1; for (int i = n; i >= n - k + 1; i--) { ans = ans % mod * a[i] % mod; } return ans; } LL get_max(int b, int tar) { LL ans = 1; for(int i = 1; i <= k; i++) { if(i != b) { ans = ans % mod * a[i] % mod; } } if(b != -1) ans = ans % mod * a[tar] % mod; return ans; } int main() { scanf("%d%d", &n, &k); for (int i = 1; i <= n; i++) scanf("%lld", &a[i]); sort(a + 1, a + n + 1, cmp); int cnt = 0, p1 = -1, p2 = -1, m1 = -1, m2 = -1; LL ans = 1; for (int i = 1; i <= k; i++) if (a[i] < 0) cnt++; if (cnt & 1) // 绝对值最大的k个数字只能得到负数 { for (int i = k; i; i--) { if (p1 != -1 && m1 != -1) break; if (p1 == -1 && a[i] > 0) p1 = i; if (m1 == -1 && a[i] < 0) m1 = i; } for (int i = k + 1; i <= n; i++) { if (p2 != -1 && m2 != -1) break; if (p2 == -1 && a[i] > 0) p2 = i; if (m2 == -1 && a[i] < 0) m2 = i; } bool f1 = true, f2 = true; if(m1 != -1 && p2 != -1) { f1 = false; ans = get_max(m1, p2); } if(p1 != -1 && m2 != -1) { f2 = false; ans = max(ans, get_max(p1, m2)); } if (f1 && f2) // 无法得到正数 { ans = get_min(); } } else ans = get_max(-1, -1); printf("%lld\n", ans); return 0; }
这是贪心正解:
我们可以先考虑只有正数的情况,这时候只要选最大的数就行了;
而引入负数之后,因为负负得正,有可能会把原来最小的给反转成最大的,那么这时候,我们只要再把这个反转的可能性考虑进来即可,实现方式就是既考虑最大的那一头,也考虑最小的那一头。
#include<bits/stdc++.h> #define int long long #define mod 1000000009 using namespace std; int n,k,a[100005],ans; signed main() { cin>>n>>k; for(int i=1;i<=n;i++) cin>>a[i]; sort(a+1,a+n+1); ans=k&1?a[n]:1; n-=k&1; k-=k&1; int l=1,r=n,f=ans<0?-1:1; while(k) { int p=a[l]*a[l+1],q=a[r]*a[r-1];//两端取 if(p*f>q*f)//贪心选取 { ans=p%mod*ans%mod; l+=2; } else { ans=q%mod*ans%mod; r-=2; } k-=2; } cout<<ans; return 0; }
本文作者:Gold_stein
本文链接:https://www.cnblogs.com/smartljy/p/18033177
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?