[Offer收割]编程练习赛12 题目4 : 寻找最大值

时间限制:10000ms

单点时限:1000ms

内存限制:256MB

描述

给定N个数A1, A2, A3, ... AN,小Ho想从中找到两个数Ai和Aj(i ≠ j)使得乘积Ai × Aj × (Ai AND Aj)最大。其中AND是按位与操作。

小Ho当然知道怎么做。现在他想把这个问题交给你。

输入

第一行一个数T,表示数据组数。(1 <= T <= 10)

对于每一组数据:

第一行一个整数N(1<=N<=100,000)

第二行N个整数A1, A2, A3, ... AN (0 <= Ai <220)

输出

一个数表示答案

样例输入
2
3
1 2 3
4
1 2 4 5
样例输出
12
80

思路

(1)优化穷举。先对整数从小到大排序,从后往前求解数对的结果,并更新max。对于a,b两个数,Ai × Aj × (Ai AND Aj)的最大值为 a * b * Math.min(a, b),因此可以利用此性质对O(n^2)的解法进行优化。

(2)贪心。先对整数从小到大排序,Ai × Aj × (Ai AND Aj)的最大值只有可能出现在排序后相邻的两个元素的情况(Why?

代码

(1)

 1 import java.util.Arrays;
 2 import java.util.Scanner;
 3
 4 public class BasicMain {
 5
 6     public static long max(int[] nums) {
 7         final int n = nums.length;
 8         long max = 0;
 9         for (int i = n - 1; i >= 0; i--) {
10             for (int j = n - 1; j > i; j--) {
11                 long tmp = (long) nums[i] * nums[j];
12                 if (tmp * nums[i] <= max)  // 优化,后续不可能有超过max的值
13                     break;
14
15                 max = Math.max(max, tmp * (nums[i] & nums[j]));
16             }
17         }
18         return max;
19     }
20
21     public static void main(String[] args) {
22         Scanner sc = new Scanner(System.in);
23         int cases = sc.nextInt();
24         for (int c = 0; c < cases; c++) {
25             int n = sc.nextInt();
26             int[] nums = new int[n];
27             for (int i = 0; i < n; i++) {
28                 nums[i] = sc.nextInt();
29             }
30             Arrays.sort(nums);
31             System.out.println(max(nums));
32         }
33     }
34 }

(2)

 1 import java.util.Arrays;
 2 import java.util.Scanner;
 3
 4 public class Main {
 5
 6     public static long max(int[] nums) {
 7         final int n = nums.length;
 8         long max = 0;
 9         for (int i = 0; i < n - 1; i++) {
10             max = Math.max(max, (long) nums[i] * nums[i + 1] * (nums[i] & nums[i + 1]));
11         }
12         return max;
13     }
14
15     public static void main(String[] args) {
16         Scanner sc = new Scanner(System.in);
17         int cases = sc.nextInt();
18         for (int c = 0; c < cases; c++) {
19             int n = sc.nextInt();
20             int[] nums = new int[n];
21             for (int i = 0; i < n; i++) {
22                 nums[i] = sc.nextInt();
23             }
24             Arrays.sort(nums);
25             System.out.println(max(nums));
26         }
27     }
28 }
时间: 2025-01-12 13:31:56

[Offer收割]编程练习赛12 题目4 : 寻找最大值的相关文章

[Offer收割]编程练习赛12 题目1 : 歌德巴赫猜想

时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 哥德巴赫猜想认为"每一个大于2的偶数,都能表示成两个质数之和". 给定一个大于2的偶数N,你能找到两个质数P和Q满足P<=Q并且P+Q=N吗? 输入 一个偶数N(4 <= N <= 1000000) 输出 输出P和Q.如果有多组解,输出P最小的一组. 样例输入 10 样例输出 3 7 思路 判断和为N两个数是否为素数 代码 1 import java.util.Scanner; 2 3 pu

[Offer收割]编程练习赛12 题目2 : 一面砖墙

时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi的学校的教学楼前有一面砖墙.这面墙由N层砖砌成,其中从上到下第i层包含Ci块高度相同但宽度不同的砖. 例如下图所示的这面墙,由3层砖砌成.其中第1层包含3块砖,从左到右宽度依次是6.4和3:第2层包含4块砖,从左到右依次宽度依次是4.4.2和3:第3层包含3块砖,从左到右宽度依次是5.6和2. +------------+ | 6 | 4 |3 | +------------+ | 4 | 4 |2|3 | +-

[Offer收割]编程练习赛12 题目3 : 矩形分割

时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi有一块由NxM个单位正方形组成的矩形.现在小Ho在某些单位正方形上画了一道分割线,这条分割线或者是单位正方形的主对角线(用'\'表示),或者是副对角线(用'/'表示). 现在小Hi想知道这些分割线把NxM的矩形分割成了多少块区域. 例如 /\/ 就把2x2的矩形分成了5个区域. /\/\ / \/ 把3x4的矩形分成了7个区域. 输入 第一包含两个整数N和M.(1 <= N, M <= 100) 以下N行每行包

hihocoder offer收割编程练习赛12 D 寻找最大值

思路: 可能数据太水了,随便乱搞就过了. 实现: 1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 using namespace std; 5 typedef long long ll; 6 7 int a[100005], n; 8 9 int main() 10 { 11 int t; 12 cin >> t; 13 while (t--) 14 { 15 ll max

hihocoder offer收割编程练习赛12 C 矩形分割

思路: 模拟,深搜. 实现: 1 #include <iostream> 2 #include <cstdio> 3 #include <string> 4 using namespace std; 5 6 const int dx[4] = { 0, 1, 0, -1 }; 7 const int dy[4] = { -1, 0, 1, 0 }; 8 9 int n, m, cnt = 0; 10 int a[305][305]; 11 bool vis[305][3

hihocoder offer收割编程练习赛12 A 歌德巴赫猜想

思路: 枚举. 实现: 1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 using namespace std; 5 6 const int MAX_N = 1000005; 7 8 int prime[MAX_N]; 9 bool is_prime[MAX_N + 1]; 10 11 int init(int n) 12 { 13 int p = 0; 14 for (int i =

[Offer收割]编程练习赛11 题目2 : 物品价值

时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi现在有n个物品,每个物品都有一个价值.并且这n个物品总共有m个不同的属性,每个物品都具有其中若干属性. 小Ho要从中选出若干物品,满足每个属性都正好有奇数个物品拥有,且被选出的物品价值总和最大.你能帮助小Ho完成任务么? 输入 第一行一个数T(<=10),表示数据组数.对于每一组数据: 第一行两个数n,m(1<=n<=1000,m<=10) 接下来每两行描述一件物品.对于每一件物品: 第一行两个数v

[Offer收割]编程练习赛11 题目3 : 岛屿3

时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 H国正在进行一项持续N周的填海造岛工程.整片工程海域可以被看作是1000x1000的网格. 每周都有一块1x1的单位方格海域被填成陆地.如果我们将连成一片的陆地(一块单位方格与它上下左右4个单位方格是相连的)视为岛屿,H国想监测每周末整片海域中一共存在有多少个岛屿,以及这些岛屿的总面积和总周长各是多少. 假设工程持续三周,第一周被填的海域坐标是(0, 0),那么第一周结束后有1座岛屿.总面积是1.总周长是4: #..

[Offer收割]编程练习赛11 题目1 : hiho字符串

时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 如果一个字符串恰好包含2个'h'.1个'i'和1个'o',我们就称这个字符串是hiho字符串. 例如"oihateher"."hugeinputhugeoutput"都是hiho字符串. 现在给定一个只包含小写字母的字符串S,小Hi想知道S的所有子串中,最短的hiho字符串是哪个. 输入 字符串S 对于80%的数据,S的长度不超过1000 对于100%的数据,S的长度不超过100000 输