• HihoCoder


    描述

    给定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

    思路:Ai*Aj*(Ai&Aj)我们枚举第三部分,假设第三部分为x=Ai&Aj,然后我们取x的超集的最大值和次大值即可。

    对于每个Ai我们可以枚举子集,用Ai取更新子集的最大次大值。4777ms;

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=(1<<20)+10;
    int Mx[maxn],Se[maxn]; long long ans;
    int main()
    {
        int T,N,x;
        scanf("%d",&T);
        while(T--){
            memset(Mx,0,sizeof(Mx));
            memset(Se,0,sizeof(Se));
            scanf("%d",&N);
            for(int i=1;i<=N;i++){
                scanf("%d",&x);
                for(int j=x;j;j=(j-1)&x){
                    if(x>Mx[j]){
                        Se[j]=Mx[j]; Mx[j]=x;
                    }
                    else if(x>Se[j]) Se[j]=x;
                }
            }
            ans=0;
            for(int i=1;i<maxn;i++) ans=max(ans,(long long)i*Mx[i]*Se[i]);
            printf("%lld
    ",ans);
        }
        return 0;
    }

    也可以利用高维前缀和来维护最大次大值。1586ms。

    (目前见到的三种:高维前缀和维护了X集之和,位置的最小值,最大次大值。ORZ

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int maxn=1<<20;
    int Mx[maxn+10],Se[maxn+10]; ll ans;
    int main()
    {
        int T,N,x;
        scanf("%d",&T);
        while(T--){
            memset(Mx,0,sizeof(Mx));
            memset(Se,0,sizeof(Se));
            scanf("%d",&N);
            for(int i=1;i<=N;i++){
                scanf("%d",&x);
                if(x>Mx[x]) Mx[x]=x;
                else Se[x]=x;
            }
            for(int i=0;i<20;i++){
                for(int j=0;j<maxn;j++){
                    if(!(j&(1<<i))){
                        if(Mx[j|(1<<i)]>=Mx[j]){
                            Se[j]=max(Mx[j],Se[j|(1<<i)]);
                            Mx[j]=Mx[j|(1<<i)];
                        }
                        else Se[j]=max(Mx[j|(1<<i)],Se[j]);
                    }
                }
            }
            ans=0;
            for(int i=1;i<maxn;i++) ans=max(ans,(ll)i*Mx[i]*Se[i]);
            printf("%lld
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    Python爬虫连载9-JS加密之“盐”​、ajax请求
    Java连载86-List集合详解
    HTML连载69-透视属性以及其他属性练习
    Java连载85-集合的Contains和Remove方法
    Python爬虫连载8-JS加密(一)
    Java连载84-Collection的常用方法、迭代器
    HTML连载68-形变中心点、形变中心轴
    Java连载83-单向链表、双向链表、collections常用方法
    [刷题] 447 Number of Boomerangs
    [刷题] 454 4Sum II
  • 原文地址:https://www.cnblogs.com/hua-dong/p/9950645.html
Copyright © 2020-2023  润新知